我有以下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
元素的模式?
答案 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>
声明为此类型的扩展名。