我必须编写一个将一些数据导出为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中编写模式的扩展。用扩展模式编写第二个模式文件可能不是一种选择。
提前致谢!
安德烈
答案 0 :(得分:1)
是的,XSD旨在支持所有常用的支持DTD扩展的技术,还有一些。 helderdarocha的答案草拟了一些方法。
扩展您正在使用的标准架构究竟应该做些什么取决于您希望遵循的标准如何允许您扩展架构。如果您指定的DTD片段的类比是精确的,则基本模式似乎可能使用通配符编写,以允许用户定义的元素位于适当的位置。如果是这样,那么您需要做的就是定义新元素,最好是在您自己的命名空间中,并将标准模式和模式文档的位置发送给验证器。如果不知道标准模式是如何编写的,或者规范中有关扩展的说法,那么就不可能更精确。
如果标准架构是公开的,您可能希望提供一个链接,以便人们检查它并查看您需要做什么。
答案 1 :(得分:0)
您当然可以扩展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_ONE
和ELEMENT_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
,然后使用属性{{1}从ROOT
引用它}。
解析器也可以尝试验证整个文档而不跳过xsi:noNamespaceSchemaLocation="#schemaName"
块。如果发生这种情况,它会抱怨错误放置的xs:schema
元素。您可以修改为xs:schema
中的xs:schema
元素添加声明(如上面的代码所示)。