从子节点排除元素的XPath选择



我需要选择所有<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>

相关内容

  • 没有找到相关文章

最新更新