开发者

Using entity 'constants' in an XML Schema

开发者 https://www.devze.com 2023-03-15 21:38 出处:网络
I am trying to create an XML schema in which a lot of types are sharing some \'magic numbers\'. Instead of having to change my schema in several locations if/when these magic numbers change, I would

I am trying to create an XML schema in which a lot of types are sharing some 'magic numbers'.

Instead of having to change my schema in several locations if/when these magic numbers change, I would like to pull them out into some kind of constant definition.

I have played around with adding a DTD to my schema and declaring some entities here. But I am by no means an expert on DTD, and while it seems to work in a C# application that uses the schema, there is also a native Win32 application that uses the same schema with msxml 4.0 where this blows up...

Does anyone have experience with extending the schema definition this way (can it be done), or is there a better way?

(EDIT: An example)

Example 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>

Example Delphi Win32 code to load the schema:

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;

The code asserts after attempting to lo开发者_运维知识库ad the schema. Reason: 'The name of the top most element must match the name of the DOCTYPE declaration.'


Yes, you can use entities to define constants in an XML Schema file.

The code asserts after attempting to load the schema. Reason: 'The name of the top most element must match the name of the DOCTYPE declaration.'

<?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>

Your problem is caused by the fact that DTDs are not namespace aware. Because of this, the parser sees a DTD that defines the root element <schema> whereas your document has a root element <xs:schema>. Try using <!DOCTYPE xs:schema [ instead. This prefix "hardcoding" might seem erroneous but in DTD there is no easy general way to have a namespace prefix mapping.

If you use the same "magic numbers" in several schemas, then you could also define the entities in a separate DTD and then include that by referring to it via an parameter entity in your embedded DTD.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xs:schema [
  <!ENTITY % magicNumbers SYSTEM "url/to/your/entity/dtd-document">
  %magicNumbers;
]>
<xs:schema ... >


A W3C Schema XSD is an XML document, so entities are allowed and supported. When the Schema file is read and processed, the entities will be expanded to produce the XML infoset.

http://www.xml.com/pub/a/2002/02/27/q-and-a.html

By the way, an XSD is itself an XML document, of course, so there's nothing preventing you from using entities within the Schema itself. (This is a little perverse, requiring the Schema to use a DTD to declare those entities.) You just can't use XML Schema to declare entities for use in other documents.

Entities can be a convenient way to avoid copy/paste and ease maintenance of XML instance files.

If it "blows up" in the native Win32 app when it parses the schema it sounds like a bug in MSXML 4.0 or the native Win32 app.


You can make a common xsd, and import it from the other schemas. See Importing Types.

The report schema, report.xsd, makes use of the simple type xipo:SKU that is defined in another schema, and in another target namespace.

<import namespace="http://www.example.com/IPO"/>
0

精彩评论

暂无评论...
验证码 换一张
取 消