【问题标题】:Extend existing XSD in XML在 XML 中扩展现有的 XSD
【发布时间】:2014-05-26 14:39:39
【问题描述】:

我必须编写一个将一些数据导出为 XML 的应用程序。 我的应用程序应该导出的 XML 是给定的标准。 该标准允许使用 DTD 或 XSD 进行验证。因为我认为 XSD 是我使用 XSD 的更好方式。

但是有一个挑战。该标准允许 XML 扩展该标准。为此,导出的 XML 必须扩展标准 XSD(或 DTD)。

对于 DTD,您可以像以下示例一样进行操作:

<!DOCTYPE ROOT "original_dtd_file.dtd"
[
<!ENTITY % USERDEFINES "(ELEMENT_ONE?,ELEMENT_TWO?)">
<!ELEMENT ELEMENT_ONE (#PCDATA)>
<!ELEMENT ELEMENT_TWO (#PCDATA)>
]
>

XSD 也可以这样吗? 编写新的 XSD 不是一种选择。

我试图通过搜索互联网获得解决方案,但我没有得到任何线索。

编辑:我认为我的问题并不完全正确。重要的一点是,模式的扩展必须写在导出的 XML 中。遗憾的是,无法使用扩展架构编写第二个架构文件。

提前致谢!

安德烈

【问题讨论】:

    标签: xml xsd


    【解决方案1】:

    您当然可以扩展 XSD。你可以做很多事情。 XML Schema 允许您包含相同命名空间的 XSD、重新定义类型、导入不同命名空间的 XSD。

    如果您有这样的 XML 实例:

    <ROOT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="base.xsd">
        <ORIGINAL_ELEMENT_1>aaa</ORIGINAL_ELEMENT_1>
        <ORIGINAL_ELEMENT_2>bbb</ORIGINAL_ELEMENT_2>
    </ROOT>
    

    由此 XSD (base.xsd) 验证:

    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
        <xs:element name="ROOT" type="RootType"/>
    
        <xs:complexType name="RootType">
            <xs:sequence>
                <xs:element name="ORIGINAL_ELEMENT_1" type="xs:string" minOccurs="0"/>
                <xs:element name="ORIGINAL_ELEMENT_2" type="xs:string" minOccurs="0"/>
            </xs:sequence>
        </xs:complexType>
    
    </xs:schema>
    

    您需要扩展它以在ROOT 中添加两个新元素,您可以创建一个新模式,在其中重新定义元素的类型并声明新元素。例如,这个:

    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    
        <xs:redefine schemaLocation="base.xsd">
            <xs:complexType name="RootType">
                <xs:complexContent>
                    <xs:extension base="RootType">
                        <xs:sequence>
                            <xs:element ref="ELEMENT_ONE" minOccurs="0"/>
                            <xs:element ref="ELEMENT_TWO" minOccurs="0"/>
                        </xs:sequence>
                    </xs:extension>
                </xs:complexContent>
            </xs:complexType>
        </xs:redefine>
    
        <xs:element name="ELEMENT_ONE" type="xs:string"/>
        <xs:element name="ELEMENT_TWO" type="xs:string"/>
    
    </xs:schema>
    

    将允许您将 ELEMENT_ONEELEMENT_TWO 添加到使用此 XSD (extended.xsd) 进行验证的文档中:

    <ROOT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="extended.xsd">
        <ORIGINAL_ELEMENT_1>aaa</ORIGINAL_ELEMENT_1>
        <ORIGINAL_ELEMENT_2>bbb</ORIGINAL_ELEMENT_2>
        <ELEMENT_ONE>xxx</ELEMENT_ONE>
        <ELEMENT_TWO>yyy</ELEMENT_TWO>
    </ROOT>
    

    如果您有不同的命名空间,您可以使用xs:import 并重用类型定义和元素来创建新的类型、元素和属性。您还可以使用xs:include 将现有架构中的类型、元素和属性简单地添加到新架构中。

    更新 - 关于内联 XSD

    您询问了内联 XSD。它们是受支持的,但据我所知,这种支持是非标准(但我可能错了)。根据我的经验,我注意到虽然有些解析器在没有任何更改的情况下支持它们,但其他解析器会抱怨 xs:schema 不是最外层元素而失败,并且有些解析器会进行一些调整。

    如果您的解析器支持它,它可能就像将 XSD 放在 ROOT 元素中一样简单:

    <?xml version="1.0" encoding="UTF-8"?>
    <ROOT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
            <xs:redefine schemaLocation="base.xsd">
                <xs:complexType name="RootType">
                    <xs:complexContent>
                        <xs:extension base="RootType">
                            <xs:sequence>
                                <xs:element name="schema" namespace="http://www.w3.org/2001/XMLSchema"
                                processContents="skip" minOccurs="0" maxOccurs="1" />
                                <xs:element ref="ELEMENT_ONE" minOccurs="0"/>
                                <xs:element ref="ELEMENT_TWO" minOccurs="0"/>
                            </xs:sequence>
                        </xs:extension>
                    </xs:complexContent>
                </xs:complexType>
            </xs:redefine>
            <xs:element name="ELEMENT_ONE" type="xs:string"/>
            <xs:element name="ELEMENT_TWO" type="xs:string"/>
        </xs:schema>
        <ORIGINAL_ELEMENT_1>aaa</ORIGINAL_ELEMENT_1>
        <ORIGINAL_ELEMENT_2>bbb</ORIGINAL_ELEMENT_2>
        <ELEMENT_ONE>xxx</ELEMENT_ONE>
        <ELEMENT_TWO>yyy</ELEMENT_TWO>
    </ROOT>
    

    这适用于 Microsoft 解析器和在线服务,例如 http://www.xmlvalidation.com

    某些基于 Apache XSV 的解析器可能找不到您的架构,除非您将 id='schemaName' 添加到您的 xs:schema 元素,然后使用属性 xsi:noNamespaceSchemaLocation="#schemaName" 从您的 ROOT 引用它。

    解析器也可以尝试验证整个文档而不跳过xs:schema 块。如果发生这种情况,它会抱怨错位的xs:schema 元素。您可以解决这个问题,在您的 xs:sequence 中添加 xs:schema 元素的声明(如上面的代码所示)。

    【讨论】:

    • 您好,谢谢您的回答。关键是,我需要在导出的 XML 文件中写入模式的扩展名。请参阅我的问题编辑了解更多信息。
    • 我不确定这是否作为 XSD 标准 被支持,但是许多(或者可能是大多数)解析器都支持它。它可以简单地将 XSD 包含在ROOT 下的文档中,或者可能需要对架构和xsi 属性进行一些调整。我将添加一些想法的更新。
    • 感谢您的编辑。我会在接下来的几天里测试它并写下我的经验。
    【解决方案2】:

    是的,XSD 旨在支持所有用于支持 DTD 扩展的常用技术,以及其他一些技术。 Holderdarocha 的回答概述了一些方法。

    您应该如何扩展您正在使用的标准架构,这取决于您希望遵循的标准如何允许您扩展架构。如果与您指定的 DTD 片段的类比是准确的,那么似乎基本模式是用通配符编写的,以允许用户定义的元素位于适当的位置。如果是这样,那么您需要做的就是定义新元素,最好在您自己的命名空间中,并将标准模式和模式文档的位置通知验证器。如果不知道标准模式是如何编写的,或者规范对扩展的描述,不可能更精确。

    如果标准架构是公开的,您可能希望提供指向它的链接,以便人们检查它并查看您需要做什么。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-28
      相关资源
      最近更新 更多