我正在尝试创建一个XML模式,其中许多类型正在共享一些“幻数”。
如果/当这些魔术数字发生变化时,我不想在几个位置更改我的模式,而是希望将它们拉出来进行某种不变的定义。
我一直在为我的架构添加DTD并在这里声明一些实体。但我绝不是DTD的专家,虽然它似乎在使用模式的C#应用程序中工作,但是还有一个本机Win32应用程序使用与msxml 4.0相同的模式,这会爆炸...
有没有人有过以这种方式扩展架构定义的经验(可以这样做),还是有更好的方法?
(编辑:一个例子)
示例XML:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE schema [
<!ENTITY SomeMagicNumber "10">]>
<xs:schema targetNamespace="http://tempuri.org/XMLSchema.xsd"
elementFormDefault="qualified"
xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="MySimpleType">
<xs:restriction base="xs:int">
<xs:maxInclusive value="&SomeMagicNumber;" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="MyIntegers">
<xs:sequence>
<xs:element name="value" type="xs:int" maxOccurs="&SomeMagicNumber;" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="MyFloats">
<xs:sequence>
<xs:element name="value" type="xs:float" maxOccurs="&SomeMagicNumber;" />
</xs:sequence>
</xs:complexType>
</xs:schema>
用于加载架构的Delphi Win32代码示例:
var
XmlSchemas: IXMLDOMSchemaCollection;
XmlSchema: IXMLDOMDocument2;
XmlDocument: IXMLDOMDocument2;
begin
XmlSchemas := CoXMLSchemaCache40.Create;
XmlSchema := CoDOMDocument40.Create;
XmlSchema.load((*INSERT SCHEMA PATH HERE*));
Assert(XmlSchema.parseError.errorCode = 0, XmlSchema.parseError.reason);
XmlSchemas.add((*INSERT SCHEMA TARGET NAMESPACE HERE*), XmlSchema);
XmlDocument := CoDOMDocument40.Create;
XmlDocument.schemas := XmlSchemas;
XmlDocument.validateOnParse := True;
end;
尝试加载架构后代码断言。原因:'最顶层元素的名称必须与DOCTYPE声明的名称相匹配。'
答案 0 :(得分:2)
W3C Schema XSD是一个XML文档,因此允许并支持实体。在读取和处理Schema文件时,将扩展实体以生成XML信息集。
http://www.xml.com/pub/a/2002/02/27/q-and-a.html
顺便说一句,XSD本身就是一个XML 文件,当然,所以有 什么都阻止你使用 Schema本身内的实体。 (这有点不正常,需要 Schema使用DTD声明 那些实体。)你就是不能用 XML Schema,用于声明要使用的实体 在其他文件中。
实体可以是避免复制/粘贴和简化XML实例文件维护的便捷方式。
如果它在解析架构时在本机Win32应用程序中“爆炸”,则听起来像是MSXML 4.0或本机Win32应用程序中的错误。
答案 1 :(得分:2)
是的,您可以使用实体在XML Schema文件中定义常量。
代码在尝试后断言 加载架构。理由:'的名字 最顶层的元素必须匹配 DOCTYPE声明的名称。'
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE schema [
<!ENTITY SomeMagicNumber "10">
]>
<xs:schema targetNamespace="http://tempuri.org/XMLSchema.xsd"
elementFormDefault="qualified"
xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
...(clipped away)
</xs:schema>
您的问题是由DTD不支持名称空间引起的。因此,解析器会看到一个定义根元素<schema>
的DTD,而您的文档有一个根元素<xs:schema>
。请尝试使用<!DOCTYPE xs:schema [
。这个前缀“hardcoding”可能看似错误,但在DTD中,没有简单的通用方法来进行命名空间前缀映射。
如果在多个模式中使用相同的“幻数”,那么您还可以在单独的DTD中定义实体,然后通过嵌入式DTD中的参数实体引用它来包含它。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xs:schema [
<!ENTITY % magicNumbers SYSTEM "url/to/your/entity/dtd-document">
%magicNumbers;
]>
<xs:schema ... >
答案 2 :(得分:0)
您可以创建一个常见的xsd,并从其他模式中导入它。请参阅Importing Types。
报告模式report.xsd使用了另一个模式和另一个目标名称空间中定义的简单类型xipo:SKU。
<import namespace="http://www.example.com/IPO"/>