过滤掉元素并一步替换元素值

时间:2018-02-07 23:30:41

标签: xslt

我正在尝试过滤掉元素,并重命名元素值,但我无法让它工作:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output encoding="UTF-8" indent="yes" method="xml"/>
    <xsl:template match="xml">
        <xsl:copy>
            <xsl:for-each select="product[matches(code, 'C17.*[^V]$')]">
                <xsl:copy>
                    <xsl:copy-of select="@*|node()"/>
                </xsl:copy>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="title">
        <xsl:copy>
         <xsl:value-of select="replace(.,'Apple','Carrot')"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

示例输入数据:

<?xml version="1.0" encoding="UTF-8"?>
<xml>
  <product>
      <code>C17020</code>
      <title>Apple</title>
   </product>
     <product>
      <code>C1723V</code>
      <title>Samsung</title>
   </product>
</xml>

我想离开<product>从C17开始,但不以V结尾。我使用C17.*[^V]$正则表达式。这部分正在运作。

问题在于重命名标题功能。如果我将此步骤添加到具有代码的新XSLT:

<xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
</xsl:template>

在开始时,它的工作原理。

我在这里做错了什么?

1 个答案:

答案 0 :(得分:3)

问题是您在匹配<xsl:copy-of select="@*|node()"/>的模板中正在进行xml。这将复制属性和子节点,购买不会应用任何模板。因此,您的模板匹配title尚未使用。

您需要在此使用xsl:apply-templates,但也要包含身份模板(您在新的XSLT代码中使用的模板),以确保code也被复制

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output encoding="UTF-8" indent="yes" method="xml"/>

    <xsl:template match="node()|@*">
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
    </xsl:template>

    <xsl:template match="xml">
        <xsl:copy>
            <xsl:for-each select="product[matches(code, 'C17.*[^V]$')]">
                <xsl:copy>
                    <xsl:apply-templates select="@*|node()"/>
                </xsl:copy>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="title">
        <xsl:copy>
         <xsl:value-of select="replace(.,'Apple','Carrot')"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

注意,您实际上可以简化您的XSLT。通过使用身份模板,您可以使用模板删除您不想复制的内容,而不是明确要复制的内容....

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output encoding="UTF-8" indent="yes" method="xml"/>

    <xsl:strip-space elements="*" />

    <xsl:template match="node()|@*">
          <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
    </xsl:template>

    <xsl:template match="product[not(matches(code, 'C17.*[^V]$'))]" />

    <xsl:template match="title">
        <xsl:copy>
         <xsl:value-of select="replace(.,'Apple','Carrot')"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

需要注意的另一件事是matchesreplace仅适用于XSLT 2.0。