問題描述
我正在編寫 xsd 和要驗證的代碼,所以我在這里可以很好地控制.
I'm writing the xsd and the code to validate, so I have great control here.
我想要一個上傳工具,可以根據 xml 文件向我的應用程序添加內容.xml 文件的一部分應根據另一部分中的值之一針對不同的模式進行驗證.下面舉個例子來說明:
I would like to have an upload facility that adds stuff to my application based on an xml file. One part of the xml file should be validated against different schemas based on one of the values in the other part of it. Here's an example to illustrate:
<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>
的內容有一些受控詞匯,我可以很好地處理這部分.然后,根據 bar 值,應使用適當的 xml 模式來驗證 bar-config 的內容.對于 baz 和 baz-config 也是如此.
In this case, there is some controlled vocabulary for the content of <bar>
, and I can handle that part just fine. Then, based on the bar value, the appropriate xml schema should be used to validate the content of bar-config. Similarly for baz and baz-config.
進行解析/驗證的代碼是用 Java 編寫的.不確定解決方案對語言的依賴性.
The code doing the parsing/validation is written in Java. Not sure how language-dependent the solution will be.
理想情況下,該解決方案將允許 xml 作者聲明適當的架構位置和其他內容,以便他/她可以在足夠智能的編輯器中即時驗證 xml.
Ideally, the solution would permit the xml author to declare the appropriate schema locations and what-not so that s/he could get the xml validated on the fly in a sufficiently smart editor.
另外,<bar>
和 <baz>
的可能值是正交的,所以我不想通過擴展來對每個可能的條進行此操作/baz 組合.我的意思是,如果有 24 個可能的 bar 值/模式和 8 個可能的 baz 值/模式,我希望能夠編寫 1 + 24 + 8 = 33 個總模式,而不是 1 * 24 * 8 = 192 個總模式.
Also, the possible values for <bar>
and <baz>
are orthogonal, so I don't want to do this by extension for every possible bar/baz combo. What I mean is, if there are 24 possible bar values/schemas and 8 possible baz values/schemas, I want to be able to write 1 + 24 + 8 = 33 total schemas, instead of 1 * 24 * 8 = 192 total schemas.
另外,如果可能的話,我不希望將 bar-config 和 baz-config 拆分為單獨的 xml 文件.我意識到這可能會使所有問題變得更容易,因為每個 xml 文件都有一個單一的架構,但我正在嘗試看看是否有一個好的單 xml 文件解決方案.
Also, I'd prefer to NOT break out the bar-config and baz-config into separate xml files if possible. I realize that might make all the problems much easier, as each xml file would have a single schema, but I'm trying to see if there is a good single-xml-file solution.
推薦答案
我終于想通了.
首先,在 foo 模式中,bar-config 和 baz-config 元素的類型包含 any
元素,如下所示:
First of all, in the foo schema, the bar-config and baz-config elements have a type which includes an any
element, like this:
<sequence>
<any minOccurs="0" maxOccurs="1"
processContents="lax" namespace="##any" />
</sequence>
那么,在 xml 中,您必須使用 bar-config 或 baz-config 的子元素上的 xmlns
屬性指定正確的命名空間,如下所示:
In the xml, then, you must specify the proper namespace using the xmlns
attribute on the child element of bar-config or baz-config, like this:
<bar-config>
<config xmlns="http://www.example.org/bar/Alpha">
... config xml here ...
</config>
</bar-config>
然后,bar Alpha 的 XML 模式文件將具有 http://www.example 的目標命名空間.org/bar/Alpha 并將定義根元素 config
.
Then, your XML schema file for bar Alpha will have a target namespace of http://www.example.org/bar/Alpha and will define the root element config
.
如果您的 XML 文件具有兩個模式文件的名稱空間聲明和模式位置,這足以讓編輯器完成所有驗證(至少對 Eclipse 來說足夠好).
If your XML file has namespace declarations and schema locations for both of the schema files, this is sufficient for the editor to do all of the validating (at least good enough for Eclipse).
到目前為止,我們已經滿足了xml作者可以以在編輯器中驗證的方式編寫xml的要求.
So far, we have satisfied the requirement that the xml author may write the xml in such a way that it is validated in the editor.
現在,我們需要消費者能夠進行驗證.就我而言,我使用的是 Java.
Now, we need the consumer to be able to validate. In my case, I'm using Java.
如果您有機會提前知道需要用于驗證的架構文件,那么您只需創建一個 Schema 對象并照常進行驗證,如下所示:
If by some chance, you know the schema files that you will need to use to validate ahead of time, then you simply create a single Schema object and validate as usual, like this:
Schema schema = factory().newSchema(new Source[] {
new StreamSource(stream("foo.xsd")),
new StreamSource(stream("Alpha.xsd")),
new StreamSource(stream("Mercury.xsd")),
});
然而,在這種情況下,在我們解析主文檔之前,我們不知道要使用哪些 xsd 文件.所以,一般的程序是:
In this case, however, we don't know which xsd files to use until we have parsed the main document. So, the general procedure is to:
- 僅使用主 (foo) 架構驗證 xml
- 確定用于驗證文檔部分的架構
- 使用單獨的架構查找作為要驗證的部分的根節點
- 將該節點導入到一個全新的文檔中
- 使用其他架構文件驗證全新的文檔
注意事項:似乎必須構建可識別命名空間的文檔才能使其正常工作.
這是一些代碼(這是從我的代碼的各個地方撕下來的,所以復制和粘貼可能會引入一些錯誤):
Here's some code (this was ripped from various places of my code, so there might be some errors introduced by the copy-and-paste):
// 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));
這篇關于要針對多個 xsd 模式驗證 XML的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!