Ric*_*uen 6 xml validation xsd xml-namespaces xmllint
我正在开发一个工具来帮助用户创作XHTML-ish文档,这些文档在性质上与JSP文件类似.这些文档是XML,可以在XHTML命名空间中包含任何格式良好的标记,并且它们之间编织的是我产品命名空间中的元素.除此之外,该工具使用XSD验证输入.
输入示例:
<?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>
Run Code Online (Sandbox Code Playgroud)
我的问题是XSD验证的行为不一致取决于我嵌套元素的深度.我想要的是https://my_tag_lib.example.com/根据模式检查命名空间中的所有元素,同时http://www.w3.org/1999/xhtml可以容忍地容忍命名空间中的任何元素.我想不列出我的XSD中允许的所有HTML元素 - 用户可能想要使用仅在某些浏览器上可用的模糊元素.相反,我只想使用白名单列出属于命名空间的任何元素<xs:any>.
我发现的是,在某些情况下,属于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>
Run Code Online (Sandbox Code Playgroud)
但后来验证失败了:
<?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>
Run Code Online (Sandbox Code Playgroud)
为什么要针对已识别元素的模式验证属性,而未识别的元素似乎根本没有被消毒?这里的逻辑是什么?我一直在xmllint用来做验证:
xmllint --schema markup.xsd example.xml
Run Code Online (Sandbox Code Playgroud)
这是我的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>
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
该div元素未声明,因此没有任何东西可以阻止 if 不接受架构中的无效类型,并且该paragraph元素不允许my-invalid-attr.
也许一些例子可以让这一点更清楚。
如果声明了该元素(例如html、section、paragraph)并且其内容来自 taglib 命名空间(您声明为拥有processContents="strict"),则它们将被视为strict。这意味着必须声明属性或子元素。这应该会导致验证失败:
<html>
<c:my-invalid-element>This is a test</c:my-invalid-element>
</html>
Run Code Online (Sandbox Code Playgroud)
这也是如此:
<c:section>
<c:my-invalid-element>This is a test</c:my-invalid-element>
</c:section>
Run Code Online (Sandbox Code Playgroud)
这:
<div>
<c:paragraph>
<c:my-invalid-element>This is a test<c:my-invalid-element>
</c:paragraph>
</div>
Run Code Online (Sandbox Code Playgroud)
这是(因为属性是内容的一部分):
<c:paragraph my-invalid-attr="true">This is a test</c:paragraph>
Run Code Online (Sandbox Code Playgroud)
但如果该元素未声明(例如div),它将与xs:any声明匹配。没有声明限制 的内容div,因此它允许任何内容。所以这应该通过验证:
<div>
<c:my-invalid-element>This is a test</c:my-invalid-element>
</div>
Run Code Online (Sandbox Code Playgroud)
并且由于c:my-invalid-element也未声明,因此它将允许任何内容或属性。这是有效的:
<div>
<c:my-invalid-element invalid-attribute="hi"> <!-- VALID -->
<c:invalid></c:invalid>
<html></html>
</c:my-invalid-element>
</div>
Run Code Online (Sandbox Code Playgroud)
但是,如果您将无效元素放入其中,它将html失败:
<div>
<c:my-invalid-element invalid-attribute="hi">
<html><c:invalid></c:invalid></html> <!-- NOT VALID -->
</c:my-invalid-element>
</div>
Run Code Online (Sandbox Code Playgroud)
如果您在声明的元素内使用未声明的属性(将不匹配xs:any),无论您的嵌套有多深,都会发生同样的情况:
<div>
<c:my-invalid-element invalid-attribute="hi"> <!-- VALID -->
<c:invalid>
<b>
<c:section bad-attribute="boo"></c:section> <!-- FAILS! -->
...
Run Code Online (Sandbox Code Playgroud)