我正在嘗試記錄其他人手工編碼的 XML,我希望 XSD 能幫助我做到這一點。然而,我被無知所阻礙:我不能保證 XSD 將適用于整個事情。(如果有的話,請隨意告訴我某些代碼風格很糟糕,但我只是檔案記錄者,而不是開發人員。)
無論如何,情況是我有:
<items>
<item name="foo">
<coolThing>wah!</coolThing>
</item>
<item name="bar">
<needfulThing>address</needfulThing>
</item>
</items>
(實際用詞當然是編造的。)<coolThing>元素只能出現在一個<item name="foo">容器中,而<needfulThing>元素只能出現在一個<item name="bar">容器中。
我如何在 XSD 中指定它?我正在查看的教程方便地忽略了這一點。
是否像將各種元素定義為屬性宣告的子元素一樣簡單:
<xs:attribute name="foo" type="xs:string">
<xs:element name="coolThing" type="xs:string"/>
</xs:attribute>
(為了清楚起見,已經省略了一些內容。)當然,如果發生這種情況,這不會讓我很容易地指定<coolThing>可以同時出現在<item name="foo">和 a<item name="baz">元素中。
或者我錯過了什么?(很有可能。)
uj5u.com熱心網友回復:
是的,您忽略了 XSD(以及其他 XML 模式)的設計目的是將元素與基于元素名稱的型別相關聯,而不是基于元素的屬性。
出于這個原因,使用過于通用的元素,例如item或object或thing通過屬性區分的,例如name被認為是反模式。XSD 1.1 具有允許表達此類約束的斷言機制,但實際上您將通過斷言人為地重新實作自然包含約束——而不是您想要的位置。
具體來說,不是一般地設計您的 XML 元素,
<item name="foo"/>
讓它們的元素名稱傳達它們的性質:
<foo/>
然后您會發現 XSD 1.0 中可用的普通內容模型足以表達您的包含約束。
更新:Michael Kay 讓我想起了另一種 XSD 1.1 機制,它不如斷言強大,但如果您只需要改變每個屬性值的型別,則更適合:條件型別分配...
如果您堅持使用過于通用的元素名稱并試圖在事后撰寫架構,那么在 XSD 1.1 的斷言之前,請考慮 XSD 1.1 的Conditional Type Assignment,它允許根據屬性值分配型別。
一個完整的作業示例可以在這里找到:
- 如何使用條件型別分配使型別依賴于屬性值
uj5u.com熱心網友回復:
您可以使用 XSD 1.1 執行此操作,并帶有型別替代項。例如,參見XSD 1.1 替代使用問題。這個特性被明確設計來做你想做的事情——使元素的型別取決于屬性的值,而不是元素的名稱。
但是您需要一個 XSD 1.1 處理器。我知道三個:Altova、Saxon 和 Apache Xerces。許多廣泛使用的 XSD 處理器,例如 Microsoft 的,從未更新到 XSD 1.1。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/331658.html
