如何允许XML元素通过XSD出现在任何地方?

时间:2017-04-13 12:07:11

标签: xml xsd

我有以下XML:

<root>
  <someNode>
    <someChild attr="val" />
  </someNode>

  <otherNode>
    <otherChild>
      <otherSubChild />
    </otherChild>
  </otherNode>
</root>

有效的XML Schema非常简单。现在的问题是,我的程序必须支持在解析文件时评估的特殊元素,并导致元素的条件替换。

示例:

    <root>
      <someNode>
        <if environment="DEV">
          <someChild attr="val" />
        </if>
        <if environment="PROD">
          <someChild attr="otherVal" />
        </if>
      </someNode>

      <otherNode>
        <otherChild>
          <if environment="DEV">
            <otherSubChild />
          </if>
        </otherChild>
      </otherNode>
    </root>

我想你明白了。问题是,允许if元素在XML中出现无处不在,但同时允许包含元素允许的任何元素它被放入。

我如何以一种好的方式定义它?目前我的XML模式中有大约90个类型/元素,手动编辑每个单独的类型/元素以允许if元素允许正确的子元素非常麻烦。

如上所述,是否可以制作允许if元素的模式?

3 个答案:

答案 0 :(得分:1)

因此,您已经指定了内容模型的层次结构,这些内容模型具体说明哪些元素可以出现在其他元素中,数量以及可能的顺序中。现在你要添加,顺便说一下,if元素可以将任何现有元素包装在任何地方吗?

您无法在XSD中执行此操作。您无法以这种方式全局对抗所有特定约束,而无需修改这些特定说明,或者没有对此进行相关规定。先验的可能性。 (例如,如果您定义了element substitution group,可能会在整个文档中出现多个位置,则可以轻松地向该组添加新成员。)

可以说任何元素都可以出现在内容模型中的给定位置(xs:any),但没有办法说某个元素可以出现在所有内容模型的任何位置。在XSD 1.1中,有一种新的机制可以在内容模型中允许open content,但这也允许前瞻性规定,而不是追溯性的全局调整。

一个建议可能是在XML的with-if和without-if形式之间编写一个简单的XSLT转换,并单独验证这些文档。

另一种方法是将您的条件表达为将出现在任何元素上的属性,而不是可以包装任何其他元素的元素。这仍然需要更新您的XSD,但在保留现有内容模型的同时更容易进行更新。

答案 1 :(得分:1)

尽管这个答案来得很晚,但我认为我会为完整性和未来的读者做出贡献。

如果验证规则很重要,我会建议kjhughes的answer中的if属性。 OTOH,OP并没有指定是否必须验证<if>,只是寻求一种通用的,非侵入性的,基于XML模式的解决方案。

如果不需要验证<if>,则处理指令(PI)可以满足OP的要求:根本无需编辑架构,就可以用来定义替代内容取决于目标环境(DEV / PROD)。

这正是PI设计的目的:它们不会向xml数据添加内容(或者至少我们不应该在其中添加内容);它们未经验证;它们仅对数据的“处理器”添加含义。解析XML的应用程序不需要理解它们(当然,这取决于您对它们的处理方式)。

<root>
  <someNode>
    <?environment DEV?>
    <someChild attr="val" />

    <?environment PROD?>
    <someChild attr="otherVal" />
  </someNode>

  <otherNode>
    <otherChild>
      <?environment DEV?>
      <otherSubChild />
    </otherChild>
  </otherNode>
</root>

注意事项:根据架构的不同,在<someChild>中包含2个<someNode>可能是无效的,在这种情况下,此文档在验证之前需要进行预处理,但是对于{ {1}}属性选项。

答案 2 :(得分:0)

也许您可以尝试为<if>元素及其属性定义基本complexType,然后将<someChild><otherChild>声明为此类型的扩展名。