MyK*_*ey_ 10 xml xslt xsd insert
我有一个带有一些可选节点的现有XML文档,我想插入一个新节点,但是在某个位置.
该文档看起来像这样:
<root>
<a>...</a>
...
<r>...</r>
<t>...</t>
...
<z>...</z>
</root>
Run Code Online (Sandbox Code Playgroud)
所述新节点(<s>...</s>)应节点之间插入<r>和<t>,导致:
<root>
<a>...</a>
...
<r>...</r>
<s>new node</s>
<t>...</t>
...
<z>...</z>
</root>
Run Code Online (Sandbox Code Playgroud)
问题是,现有节点是可选的.因此,我不能使用XPath来查找节点<r>并在其后插入新节点.
我想,以避免"暴力法":从搜索<r>多达<a>发现存在一个节点.
我还想保留顺序,因为XML文档必须符合XML模式.
可以使用XSLT以及普通的XML库,但由于我只使用Saxon-B,因此不能选择模式感知的XSLT处理.
有没有人知道如何插入这样的节点?
thx,MyKey_
Eva*_*enz 19
[取代我的最后答案.现在我更了解你需要什么.]
这是一个XSLT 2.0解决方案:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/root">
<xsl:variable name="elements-after" select="t|u|v|w|x|y|z"/>
<xsl:copy>
<xsl:copy-of select="* except $elements-after"/>
<s>new node</s>
<xsl:copy-of select="$elements-after"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
您必须明确列出之后的元素或之前的元素.(你不必同时列出两者.)我倾向于选择两个列表中较短的一个(因此在上例中为"t" - "z",而不是"a" - "r").
可选增强:
这可以完成工作,但现在您需要在两个不同的位置(在XSLT和模式中)维护元素名称列表.如果它变化很大,那么它们可能会失去同步.如果向模式添加新元素但忘记将其添加到XSLT,则不会复制它.如果您对此感到担心,可以实现自己的架构感知.假设您的架构如下所示:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="a" type="xs:string"/>
<xs:element name="r" type="xs:string"/>
<xs:element name="s" type="xs:string"/>
<xs:element name="t" type="xs:string"/>
<xs:element name="z" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Run Code Online (Sandbox Code Playgroud)
现在您需要做的就是更改$ elements-after变量的定义:
<xsl:variable name="elements-after" as="element()*">
<xsl:variable name="root-decl" select="document('root.xsd')/*/xs:element[@name eq 'root']"/>
<xsl:variable name="child-decls" select="$root-decl/xs:complexType/xs:sequence/xs:element"/>
<xsl:variable name="decls-after" select="$child-decls[preceding-sibling::xs:element[@name eq 's']]"/>
<xsl:sequence select="*[local-name() = $decls-after/@name]"/>
</xsl:variable>
Run Code Online (Sandbox Code Playgroud)
这显然更复杂,但现在您不必在代码中列出任何元素("s"除外).每当您更改架构时,脚本的行为都会自动更新(特别是,如果您要添加新元素).这是否过度取决于您的项目.我只是将其作为可选附件提供.:-)