解决XML子元素的问题

时间:2014-05-02 23:18:36

标签: xml xsd xsd-validation xerces xerces-c

基本上我的问题是是否有办法根据给定的XSD架构验证非根元素。

我目前正在研究一些遗留代码,我们有一些C ++类以字符串格式生成XML元素。

我正在考虑通过验证生成的XML来单元测试这些类的方法(我在底层使用Xerces C ++)。问题是我无法引用与根不同的另一个模式中的元素。

这是我正在做的更详细的描述:

我有一个名为BooGenerator的类,可以生成一个' booIsNotRoot'在'foo.xsd'中定义的元素。请注意,' boo'不是根元素: - )

我创建了一个test.xsd架构,该架构引用了“booIsNotRoot'通过以下方式:

<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns="http://acme/2014/test"
            xmlns:foo="http://acme/2014/foo"
            targetNamespace="http://acme/2014/test"
            elementFormDefault="qualified">
  <xsd:import namespace="http://acme/2014/foo" schemaLocation="foo.xsd"/>
  <xsd:complexType name="TestType">
    <xsd:choice minOccurs="1" maxOccurs="1">
      <xsd:element ref="foo:booIsNotRoot"/>
    </xsd:choice>
  </xsd:complexType>
  <xsd:element name="test" type="TestType"/>
</xsd:schema>

然后我用BooGenerator生成的字符串包含一个测试元素:

<test xmlns="xmlns="http://acme/2014/test"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:foo="http://acme/2014/foo
      xsi:schemaLocation="http://acme/2014/test test.xsd">
  (code generated by BooGenerator prefixed with 'foo')
</test>

但正如我之前说过的那样,它不起作用。如果我在foo.xsd中引用根元素,它就可以了。所以我想知道是否有办法解决这个问题。

提前致谢。

2 个答案:

答案 0 :(得分:1)

是的,完全有可能。 XSD验证定义为从XML文档中的某个节点开始并验证它(通常需要验证其所有后代),因此针对指定元素声明或类型定义验证特定元素的请求是完全一致的。

如何将这样的请求传达给XSD验证器是特定于实现的(并且XSD没有规定特定的API或命令行界面,因此符合XSD验证器没有义务支持所有启动的方法XSD规范第5.2节中定义的验证事件);您将不得不查阅实施文档。我认为支持此类验证的最常用方法是使用适当的XML元素,模式和类型定义或元素声明对象在实现的XSD库中调用方法。我没有看到任何支持在其他地方开始验证的XSD验证器的命令行界面。

答案 1 :(得分:0)

Basically my question is whether or not there is way to validate a non-root 
element according to a given XSD schema.

从理论上讲,是的,XSD建议书的Section 5.2 Assessing Schema-Validity允许非根元素有效性评估。 (感谢并感谢C. M. Sperberg-McQueenpointing this out。)

实际上,不,不是直接。 XML Schema工具倾向于验证XML文档 - 未选择,单个元素 - 并且XML文档必须具有单个根元素。也许您可以在一个模拟元素的祖先的模拟上下文中嵌入您想要验证的元素,直到文档的正确根元素。

  

如果我引用foo.xsd中的根元素,它就可以工作。

实际上,foo.xsd中的根元素最好是xsd:schema。你可能想说

  

如果我在foo.xsd中引用了一个全局定义的元素(在xsd:schema下),那么它就可以了。

这也是@ref定义为在XML Schema中工作的方式 - 它不能引用本地定义的元素,例如foo:booIsNotRoot。此外,任何全局定义的元素都可以作为根元素。 (事实上​​,只有 全局定义的元素可以作为根元素。)

因此,您的选择包括:

  1. 设置一个有效的上下文来测试您的目标元素。
  2. 使您的目标元素在其XSD中全局定义。
  3. 确定XSD验证程序的特定于实现的界面 提供元素级验证。