我需要选择所有<next>
节点,但从每个节点中排除<element4>
,并在其位置添加一个新元素(这将是一个替换)。我正在使用php。
<root>
<next>
<node>
<element1>text</element1>
<element2>text</element1>
<element3>text</element1>
<element4>text</element1>
</node>
<node>
<element1>text</element1>
<element2>text</element1>
<element3>text</element1>
<element4>text</element1>
</node>
</next>
</root>
所以它应该是这样的:
<next>
<node>
<element1>text</element1>
<element2>text</element1>
<element3>text</element1>
<new>text</new>
</node>
<node>
<element1>text</element1>
<element2>text</element1>
<element3>text</element1>
<new><int xmlns="foo.bar">0</int></new>
</node>
</next>
有什么建议吗?非常感谢。
XPath是一种选择语言:它从输入序列中选择节点或原子项,是对XML或层次数据进行选择的首选语言,就像SQL(通常)是关系数据库的首选语言一样。
因此,您可以从选择中排除元素,但不能更新或更改原始序列。可以进行有限的转换(即,将字符串转换为整数),但这将更改所选内容,而不会更改源。虽然XPath(即2.0及以上版本)可以动态"创建"原子值,但它不能创建新元素。
这是可能的,并且将在XPath 2.0:中返回数值
/next/node/number(.)
但这是不可能的:
/next/node/(if (element4) then create-element(.) else .)
但是,在XSLT2.0及更高版本中,您可以创建一个创建元素的函数。如上所述,XPath选择,如果您想更改文档,可以使用XSLT创建一个新文档(T代表转换)。
类似于以下内容(部分XSLT2.0,您需要添加头):
<xsl:function name="f:create">
<xsl:param name="node" />
<xsl:param name="name" />
<xsl:choose>
<xsl:when test="name($node) = $name">
<xsl:element name="{if(number($node)) then 'int' else 'new'}">
<xsl:value-of select="$node" />
</xsl:element>
</xsl:when>
<xsl:otherwise><xsl:copy-of select="$node" /></xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:template match="node">
<!-- now XPath, with help of XSLT function, can conditionally create nodes -->
<xsl:copy-of select="child::*/create(., 'element4')" />
</xsl:template>
<!-- boilerplate code, typically used to recursively copy non-matched nodes -->
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
请注意,虽然这显示了如何使用XPath和XSLT函数创建不同的元素,但它不会更改源,而是更改输出。此外,这不是一种推荐的做法,因为在XSLT中,只需执行以下操作就可以更容易地完成相同的模式:
<!-- the more specific match -->
<xsl:template match="element4[number(.)]">
<new>
<int xmlns="foo.bar">
<xsl:value-of select="number(.)" />
</int>
</new>
<xsl:template>
<!-- XSLT will automatically fallback to this one if the former fails -->
<xsl:template match="element4">
<new><xsl:copy-of select="node()" /></new>
</xsl:template>
<!-- or this one, if both the former fail -->
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>