我写了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模式应该被用于验证杆配置的内容。同样,对于巴兹和巴兹 - 配置。
做解析/验证的代码是用Java编写。不知道该解决方案将如何与语言相关的是。
理想的情况是,该解决方案将允许XML作者声明适当的模式地点和什么,而不是让他/她可以得到一个足够聪明的编辑器在飞行验证的XML。
此外,对于<bar>
和<baz>
可能的值是正交的,所以我不希望通过延长每一个可能的酒吧/巴兹组合来做到这一点。我的意思是,如果有24个可能的酒吧值/模式和8种可能的巴兹值/模式,我希望能够写1 + 24 + 8 = 33级的总架构,而不是1 * 24 * 8 = 192级总架构。
另外,我宁愿如果可能的话不出来了吧,配置和巴兹 - 配置成单独的XML文件。我意识到,可能使所有的问题要容易得多,因为每个XML文件将有一个单一的模式,但我想看看是否有一个很好的单XML文件的解决方案。
我终于想通了这一点。
首先,在FOO模式中,杆配置和baz-配置元素具有一种类型,它包括一个any
元件,如下所示:
<sequence>
<any minOccurs="0" maxOccurs="1"
processContents="lax" namespace="##any" />
</sequence>
在XML,那么,你必须用棒或配置巴兹 - 配置,这样的子元素的xmlns
属性指定正确的命名空间:
<bar-config>
<config xmlns="http://www.example.org/bar/Alpha">
... config xml here ...
</config>
</bar-config>
然后,酒吧阿尔法XML模式文件将有http://www.example.org/bar/Alpha的目标命名空间,将定义根元素config
。
如果您的XML文件中有命名空间声明和模式位置两者的架构文件,这是足以让编辑器来完成所有的验证(至少受用的Eclipse)的。
到目前为止,我们已经满足了XML作者可以写XML,它在编辑器中验证这样的要求。
现在,我们需要消费者能够验证。就我而言,我使用Java。
如果由于某种原因,你知道你将需要使用验证的时间提前架构文件,那么你只需创建一个单一的架构对象和验证像往常一样,就像这样:
Schema schema = factory().newSchema(new Source[] {
new StreamSource(stream("foo.xsd")),
new StreamSource(stream("Alpha.xsd")),
new StreamSource(stream("Mercury.xsd")),
});
在这种情况下,然而,我们不知道要使用的XSD文件,直到我们分析的主要文件。所以,一般的程序是:
警告:看来该文件必须建立命名空间的,为了这个工作。
下面是一些代码(这是从我的代码不同的地方裂开,所以可能会有一些错误,通过复制和粘贴介绍):
// 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/
希望帮助!凯文
需要定义一个目标命名空间的实例文档的每个单独地验证的部分。然后,你定义一个使用master schema引用模式文档,这些组件的<xsd:include>
。
这种方法的限制是,你不能让个别组件定义应该被用来验证他们的模式。但它一般是一个坏主意,让文档告诉你如何进行验证(即验证应当东西,你的应用控制)。
您也可以使用“资源解析器”,让“XML作者”来指定自己的架构文件,至少在一定程度上,例如:在一天结束https://stackoverflow.com/a/41225329/32453,你想,可以是可验证的一个完全兼容的XML文件正常的工具,反正:)