我正在开发一种工具来帮助用户编写 XHTML 风格的文档,这些文档在本质上类似于 JSP 文件。这些文档是 XML,可以包含 XHTML 命名空间中任何格式正确的标记,并且在它们之间编织的是来 self 的产品命名空间的元素。除其他事项外,该工具使用 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>
我的问题是 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>
但是验证失败了:
<?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>
最佳答案
您缺少的是对 context determined declaration 的理解.
首先,看看这个小实验。
<?xml version="1.0"?>
<markup>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:c="https://my_tag_lib.example.com/">
<c:section>
<div>
<html>
<c:my-invalid-element>This is a test</c:my-invalid-element>
</html>
</div>
</c:section>
</html>
</markup>
这与您的有效示例相同,只是现在我将评估 c:my-invalid-element 的上下文从“宽松”更改为“严格”。这是通过插入 html 元素来完成的,它现在强制标记命名空间中的所有元素都是严格的。正如您可以轻松确认的那样,上述内容无效。
这告诉您(无需阅读 documentation)在您的示例中,确定的上下文一定是“松散”的,而不是您的“严格”期望。
为什么上下文松散? div
被“松散地”处理(它匹配通配符,但不存在它的定义),因此它的 child 将被松散地评估。匹配 lax 的含义:在第一种情况下,未找到 c:my-invalid-element
的定义,因此给出的指令是 don't worry if you can't
- 一切都很好。在无效示例中,可以找到 c:paragraph
的定义,因此 它必须·有效·关于该定义
- 不好,因为意外的属性.
关于xml - 使用 `<xs:any>` 对嵌套元素进行不一致的 XSD 验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22775450/