簡體   English   中英

要針對多個xsd架構驗證XML

[英]XML to be validated against multiple xsd schemas

我正在寫xsd和代碼來驗證,所以我在這里有很好的控制權。

我想有一個上傳工具,可以根據xml文件向我的應用程序添加內容。 應根據其他部分中的某個值,針對不同的模式驗證xml文件的一部分。 這是一個例子來說明:

<foo>
  <name>Harold</name>
  <bar>Alpha</bar>
  <baz>Mercury</baz>
  <!-- ... more general info that applies to all foos ... -->

  <bar-config>
    <!-- the content here is specific to the bar named "Alpha" -->
  </bar-config>
  <baz-config>
    <!-- the content here is specific to the baz named "Mercury" -->
  </baz>
</foo>

在這種情況下, <bar>的內容有一些受控的詞匯表,我可以很好地處理那部分。 然后,根據條形值,應使用適當的xml架構來驗證bar-config的內容。 同樣適用於baz和baz-config。

執行解析/驗證的代碼是用Java編寫的。 不確定解決方案的語言依賴性。

理想情況下,該解決方案將允許xml作者聲明適當的模式位置以及什么不是,以便他/她可以在足夠智能的編輯器中動態驗證xml。

此外, <bar><baz>的可能值是正交的,因此我不希望通過擴展為每個可能的bar / baz組合執行此操作。 我的意思是,如果有24個可能的條形值/模式和8個可能的baz值/模式,我希望能夠寫出1 + 24 + 8 = 33個總模式,而不是1 * 24 * 8 = 192個模式。

另外,如果可能的話,我寧願不將bar-config和baz-config分解成單獨的xml文件。 我意識到可能會使所有問題變得更容易,因為每個xml文件都有一個模式,但我正在嘗試查看是否有一個好的單xml文件解決方案。

我終於想通了。

首先,在foo架構中,bar-config和baz-config元素的類型包含any元素,如下所示:

<sequence>
    <any minOccurs="0" maxOccurs="1"
        processContents="lax" namespace="##any" />
</sequence>

在xml中,您必須使用bar-config或baz-config的子元素上的xmlns屬性指定正確的命名空間,如下所示:

<bar-config>
    <config xmlns="http://www.example.org/bar/Alpha">
        ... config xml here ...
    </config>
</bar-config>

然后,條形Alpha的XML模式文件將具有http://www.example.org/bar/Alpha的目標名稱空間,並將定義根元素config

如果您的XML文件具有兩個模式文件的名稱空間聲明和模式位置,那么編輯器就可以完成所有驗證(至少對Eclipse來說足夠好)。

到目前為止,我們已經滿足了xml作者可能以在編輯器中驗證它的方式編寫xml的要求。

現在,我們需要消費者能夠驗證。 就我而言,我正在使用Java。

如果有可能,您知道需要用於提前驗證的模式文件,那么您只需創建一個Schema對象並像往常一樣進行驗證,如下所示:

Schema schema = factory().newSchema(new Source[] {
    new StreamSource(stream("foo.xsd")),
    new StreamSource(stream("Alpha.xsd")),
    new StreamSource(stream("Mercury.xsd")),
});

但是,在這種情況下,在解析主文檔之前,我們不知道要使用哪些xsd文件。 因此,一般程序是:

  1. 僅使用main(foo)模式驗證xml
  2. 確定用於驗證文檔部分的架構
  3. 使用單獨的模式查找要驗證的部分的根節點
  4. 將該節點導入到一個全新的文檔中
  5. 使用其他模式文件驗證全新文檔

警告:似乎必須構建文檔名稱空間才能使其正常工作。

這是一些代碼(這是從我的代碼的各個地方撕掉的,因此復制和粘貼可能會引入一些錯誤):

// Contains the filename of the xml file
String filename;

// Load the xml data using a namespace-aware builder (the method 
// 'stream' simply opens an input stream on a file)
Document document;
DocumentBuilderFactory docBuilderFactory =
    DocumentBuilderFactory.newInstance();
docBuilderFactory.setNamespaceAware(true);
document = docBuilderFactory.newDocumentBuilder().parse(stream(filename));

// Create the schema factory
SchemaFactory sFactory = SchemaFactory.newInstance(
    XMLConstants.W3C_XML_SCHEMA_NS_URI);

// Load the main schema
Schema schema = sFactory.newSchema(
    new StreamSource(stream("foo.xsd")));

// Validate using main schema
schema.newValidator().validate(new DOMSource(document));

// Get the node that is the root for the portion you want to validate
// using another schema
Node node= getSpecialNode(document);

// Build a Document from that node
Document subDocument = docBuilderFactory.newDocumentBuilder().newDocument();
subDocument.appendChild(subDocument.importNode(node, true));

// Determine the schema to use using your own logic
Schema subSchema = parseAndDetermineSchema(document);

// Validate using other schema
subSchema.newValidator().validate(new DOMSource(subDocument));

看看NVDL(基於命名空間的驗證調度語言) - http://www.nvdl.org/

它旨在執行您想要執行的操作(驗證具有自己的命名空間和模式的XML文檔的部分)。

這里有一個教程 - http://www.dpawson.co.uk/nvdl/ - 這里有一個Java實現 - http://jnvdl.sourceforge.net/

希望有所幫助! 凱文

您需要為實例文檔的每個單獨驗證的部分定義目標命名空間。 然后定義一個主模式 ,該模式使用<xsd:include>來引用這些組件的模式文檔。

這種方法的局限性在於您不能讓各個組件定義應該用於驗證它們的模式。 但是一般來說,讓文檔告訴你如何驗證它是一個壞主意(即,驗證應該是你的應用程序控制的東西)。

你也可以使用“資源解析器”來允許“xml authors”指定自己的模式文件,至少在某種程度上,例如: https//stackoverflow.com/a/41225329/32453 ,在一天結束時,你想要一個完全兼容的xml文件,無論如何都可以用普通工具驗證:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM