输入示例:
<?xml version="1.0"?> <markup> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:c="https://my_tag_lib.example.com/"> <c:section> <c:paragraph> <span>This is a test!</span> <a href="http://www.google.com/">click here for more!</a> </c:paragraph> </c:section> </html> </markup>
我的问题是XSD验证的行为不一致取决于我嵌套元素的深度.我想要的是https://my_tag_lib.example.com/名称空间中的所有元素都要根据模式进行检查,而名称空间http://www.w3.org/1999/xhtml中的任何元素都可以被宽容地容忍.我想不列出我的XSD中允许的所有HTML元素 – 用户可能想要使用仅在某些浏览器等上可用的模糊元素.相反,我只想使用< xs白名单列出属于命名空间的任何元素:任何取代. 我发现的是,在某些情况下,属于my_tag_lib命名空间但未出现在模式中的元素正在通过验证,而在模式中出现的其他元素可以通过赋予它们无效属性而失败. 所以:
*有效元素根据XSD架构进行验证
*验证器会跳过无效元素?
例如,这传递验证:
<?xml version="1.0"?> <markup> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:c="https://my_tag_lib.example.com/"> <c:section> <div> <c:my-invalid-element>This is a test</c:my-invalid-element> </div> </c:section> </html> </markup>
但后来验证失败了:
<?xml version="1.0"?> <markup> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:c="https://my_tag_lib.example.com/"> <c:section> <div> <c:paragraph my-invalid-attr="true">This is a test</c:paragraph> </div> </c:section> </html> </markup>
为什么要针对已识别元素的模式验证属性,而未识别的元素似乎根本没有被消毒?这里的逻辑是什么?我一直在使用xmllint进行验证:
xmllint --schema markup.xsd example.xml
这是我的XSD文件:
文件:markup.xsd
<?xml version="1.0" encoding="ISO-8859-1" ?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xhtml="http://www.w3.org/1999/xhtml"> <xs:import namespace="http://www.w3.org/1999/xhtml" schemaLocation="html.xsd" /> <xs:element name="markup"> <xs:complexType mixed="true"> <xs:sequence> <xs:element ref="xhtml:html" /> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
文件:html.xsd
<?xml version="1.0" encoding="ISO-8859-1" ?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.w3.org/1999/xhtml"> <xs:import namespace="https://my_tag_lib.example.com/" schemaLocation="my_tag_lib.xsd" /> <xs:element name="html"> <xs:complexType mixed="true"> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:any processContents="lax" namespace="http://www.w3.org/1999/xhtml" /> <xs:any processContents="strict" namespace="https://my_tag_lib.example.com/" /> </xs:choice> </xs:complexType> </xs:element> </xs:schema>
文件:my_tag_lib.xsd
<?xml version="1.0" encoding="ISO-8859-1" ?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="https://my_tag_lib.example.com/"> <xs:element name="section"> <xs:complexType mixed="true"> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:any processContents="lax" namespace="http://www.w3.org/1999/xhtml" /> <xs:any processContents="strict" namespace="https://my_tag_lib.example.com/" /> </xs:choice> </xs:complexType> </xs:element> <xs:element name="paragraph"> <xs:complexType mixed="true"> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:any processContents="lax" namespace="http://www.w3.org/1999/xhtml" /> <xs:any processContents="strict" namespace="https://my_tag_lib.example.com/" /> </xs:choice> </xs:complexType> </xs:element> </xs:schema>
也许一些例子可能会更清楚.
如果声明了元素(例如html,section,paragraph)并且其内容来自taglib命名空间(您声明为具有processContents =“strict”),则它们将被视为严格.这意味着必须声明属性或子元素.这应该验证失败:
<html> <c:my-invalid-element>This is a test</c:my-invalid-element> </html>
这样:
<c:section> <c:my-invalid-element>This is a test</c:my-invalid-element> </c:section>
这个:
<div> <c:paragraph> <c:my-invalid-element>This is a test<c:my-invalid-element> </c:paragraph> </div>
<c:paragraph my-invalid-attr="true">This is a test</c:paragraph>
但是如果元素未声明(例如div),它将匹配xs:any声明.没有声明限制div的内容,所以它允许任何东西.所以这应该通过验证:
<div> <c:my-invalid-element>This is a test</c:my-invalid-element> </div>
由于c:my-invalid-element也未声明,因此它将允许任何内容或属性.这是有效的:
<div> <c:my-invalid-element invalid-attribute="hi"> <!-- VALID --> <c:invalid></c:invalid> <html></html> </c:my-invalid-element> </div>
但是如果将无效元素放在html中,它将失败:
<div> <c:my-invalid-element invalid-attribute="hi"> <html><c:invalid></c:invalid></html> <!-- NOT VALID --> </c:my-invalid-element> </div>
如果您在声明的元素中使用未声明的属性(与xs:any不匹配),无论您的嵌套有多深,都会发生同样的情况:
<div> <c:my-invalid-element invalid-attribute="hi"> <!-- VALID --> <c:invalid> <b> <c:section bad-attribute="boo"></c:section> <!-- FAILS! --> ...