使用XSD验证XML元素

时间:2012-10-31 15:05:50

标签: xml xsd

我有以下XML:

<?xml version="1.0" encoding="utf-8"?>
<MainElement>
    <id>1</id>
    <name>John</name>
    <custom>
        <age>43</age>
        <sex>male</sex>
    </custom>
</MainElement>

另一个XML文件:

<?xml version="1.0" encoding="utf-8"?>
<MainElement>
    <id>2</id>
    <name>Dave</name>
    <custom>
        <age>51</age>
        <county>England</country>
        <city>London</city>
    </custom>
</MainElement>

两个XML文件的主要结构相同,只有<custom>元素具有不同的实现。我已经有一个XSD文件来检查像'id'和'name'这样的元素,其中<custom>元素的类型是xs:anyType。是否可以创建另一个XSD文件,该文件仅验证<custom>元素而不查看所有其他元素?

2 个答案:

答案 0 :(得分:0)

我将为两位客户说明。第一个XSD是基本的,它应该捕获所有公共部分,除了我们引用但未定义的custom;我们把它“悬挂”。

以下是common.xsd:

<?xml version="1.0" encoding="utf-8"?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="MainElement">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="id" type="xsd:unsignedByte" />
        <xsd:element name="name" type="xsd:string" />
        <xsd:element ref="custom"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

然后我们开始为每个custom定义一个XSD。对于第一个XML(custom-1.xsd):

<?xml version="1.0" encoding="utf-8"?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="custom">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="age" type="xsd:unsignedShort"/>
                <xsd:element name="sex" type="xsd:string"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

对于第二个,custom-2.xsd:

<?xml version="1.0" encoding="utf-8"?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="custom">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="age" type="xsd:unsignedShort"/>
                <xsd:element name="country" type="xsd:string"/>
                <xsd:element name="city" type="xsd:string"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

然后,您必须通过适当加载XSD为每个客户创建一个架构集:第一个集合将包括common + custom-1,然后是common + custom-2等。

这就是我使用QTAssistant“可视化”这些集合的方式:

enter image description here

当然,Common本身无效。

Error occurred while loading [file:///.../validate-xml-element-with-xsd-2.xsd], line 9 position 10.
The 'custom' element is not declared.

但是,每个其他集合都是有效的,因为集合中的附加XSD会将缺少的定义纳入范围。现在,您可以使用其关联集验证每个供应商的XML。您可以保持跨供应商的通用定义的完整性,因为您共享一个共同的XSD,并且您使用悬挂定义在XSD 1.0中消除了“限制”。我认为这不是一个限制;它可能是一种“不那么优雅”的方法......

从处理角度来看,您需要承担与您拥有的供应商一样多次编译和加载公共XSD的开销。

如果这成为负担,一旦预处理XML的回报得到回报,您还可以使用其他策略。您可以将custom定义为anyType,甚至将其替换为xsd:any。验证通用后,您将提取节点(XSLT或DOM API或DOM节点阅读器上的验证阅读器等)并使用适当的XSD独立验证它。

后一种方法的优点是你不会在XSD方面有任何开销。当然,权衡可能会增加处理的足迹。

XSD 1.1,XSD 1.0 + Schematron,RelaxNG是涉及另一种模式语言的解决方案,它们各有优缺点。我认为上述内容至少可以帮助你理解你的一些选择......

答案 1 :(得分:0)

使用XSD,您无法使用ANY的字面含义!

所以你需要以某种方式声明所有作为XML的一部分......

我赞同你使用import / include的方法..这是一个干净的,允许进一步扩展要求..但你仍然应该知道任何元素的可能名称..

虽然不是必需的,但您会想知道另一种使用Sequencechoice来实现您的要求的方法,只有一个XSD

这是代码,它验证XML1和XML2:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="MainElement">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="id" type="xs:unsignedByte" />
        <xs:element name="name" type="xs:string" />
        <xs:element name="custom">
          <xs:complexType>
            <xs:sequence>
              <xs:choice>
                <xs:element name="age" type="xs:unsignedByte" />
              </xs:choice>
              <xs:choice>
                <xs:sequence>
                  <xs:element name="sex" type="xs:string" />
                </xs:sequence>
                <xs:sequence>
                  <xs:element name="country" type="xs:string"/>
                  <xs:element name="city" type="xs:string"/>
                </xs:sequence>
              </xs:choice>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

这对你现在可能没有用,但可能在将来......