2011-06-27 37 views
4

我正在嘗試創建一個XML模式,其中很多類型都共享一些「幻數」。在XML Schema中使用實體「常量」

如果/當這些幻數發生變化時,我不想在幾個位置更改我的模式,我想將它們拖入某種常量定義中。

我曾經在添加一個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聲明的名稱匹配。'

回答

2

是的,您可以使用實體在XML模式文件中定義常量。

該代碼在嘗試加載架構之後斷言 。原因:' 最上面的元素名稱必須與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 [代替。這個前綴「硬編碼」可能看起來是錯誤的,但在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 ... > 
+0

這似乎工作。 不幸的是,這似乎也使Visual Studio XML編輯器中的intellisense變得模糊......贏了一些,輸了一些,我猜... –

0

您可以製作一個通用的xsd,並從其他模式導入它。見Importing Types

報告模式report.xsd使用簡單類型xipo:在另一個模式中定義的SKU以及另一個目標名稱空間中的SKU。

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

雖然導入常見模式很有用,但在當前的問題上似乎沒有多大幫助。我想在我的模式中聲明實體(常量),而不是共享類型。 Mads Hansen的帖子似乎暗示這是可能的 - 但是我做錯了,不知何故...... –

2

一個W3C模式XSD是一個XML文檔,因此實體被允許和支持。當Schema文件被讀取和處理時,實體將被擴展以產生XML信息集。

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

順便說一句,一個XSD本身是一個XML文檔 當然,所以有 什麼阻止你使用模式本身 實體。 (這有些不正當,要求 Schema使用DTD聲明 這些實體。)您只是不能使用 XML架構來聲明實體在其他文檔中使用 。

實體可以是避免複製/粘貼和簡化XML實例文件維護的便捷方式。

如果它在原生Win32應用程序中「分解」模式時「爆炸」,它聽起來像是MSXML 4.0或原生Win32應用程序中的錯誤。

+0

我已經發布了一些類似於我正在嘗試做的事情的簡短示例。 –

+0

上面的模式將在C#中加載(前提是我允許在XmlReader中使用DTD)。所示的Delphi示例將失敗,因爲它似乎無法與DTD匹配到根元素......我絕不是DTD的專家 - 我在這裏聲明DTD的方式是否使其成爲內部定義,它沒有任何內容處理XMLSchema的_real_ DTD?我是否可以_extend_ XMLSchema.dtd? –