【问题标题】:Simple XSLT Text Replacement简单的 XSLT 文本替换
【发布时间】:2012-03-05 19:08:07
【问题描述】:

我正在寻找一种更简单、更优雅的方式来替换 XML 中的文本。对于像这样的源 XML:

<A>
 <B>
  <Name>ThisOne</Name>
  <Target>abc</Target>
 </B>
 <B>
  <Name>NotThisOne</Name>
  <Target>abc</Target>
 </B>
 <B>
  <Name>ThisOne</Name>
  <Target>def</Target>
 </B>
</A>

我想将名称为“ThisOne”的所有 Target 元素的文本更改为“xyz”。

结果是:

<A>
 <B>
  <Name>ThisOne</Name>
  <Target>xyz</Target>     <--   Changed.
 </B>
 <B>
  <Name>NotThisOne</Name>
  <Target>abc</Target>
 </B>
 <B>
  <Name>ThisOne</Name>
  <Target>xyz</Target>     <--   Changed.
 </B>
</A>

我通过以下方式完成了这项工作:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="B/Target">
    <xsl:choose>
      <xsl:when test="../Name/text()='ThisOne'"><Target>xyz</Target></xsl:when>
      <xsl:otherwise><Target><xsl:value-of select="text()"/></Target></xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

我在想这可以用

提前致谢。

【问题讨论】:

  • 有趣 - 几分钟内得到 3 个非常相似的答案 - 我真的很欢迎来自这里的一位真正专家的风格比较和对比。 特别是如果它指出了我的解决方案的改进
  • @Kevan - 您回答的唯一问题是,如果 &lt;Target&gt; 元素包含任何属性,它们将被剥离。
  • @DevNull - 好点 - 您的 /text() 样式不太可能出现意外行为,如果输入文档发生更改并开始在 Target 元素上具有属性 - 我很高兴我问:)

标签: xml xslt xslt-1.0


【解决方案1】:

这个样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

  <xsl:template match="B[Name='ThisOne']/Target/text()">
    <xsl:text>xyz</xsl:text>
  </xsl:template>

</xsl:stylesheet>

使用您的 XML 输入产生:

<A>
  <B>
    <Name>ThisOne</Name>
    <Target>xyz</Target>
  </B>
  <B>
    <Name>NotThisOne</Name>
    <Target>abc</Target>
  </B>
  <B>
    <Name>ThisOne</Name>
    <Target>xyz</Target>
  </B>
</A>

【讨论】:

    【解决方案2】:

    这就是你所要做的:

     <xsl:template match="@*|node()">
      <xsl:copy>
       <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match="B/Target[../Name='ThisOne']">
      <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:text>xyz</xsl:text>
      </xsl:copy>
     </xsl:template>
    

    第一个模板是“恒等变换”,将输入复制到输出不变。第二个匹配您要更改的特定目标,复制标签和属性,并替换所需的文本。

    【讨论】:

      【解决方案3】:
      <?xml version="1.0" encoding="iso-8859-1"?>
      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cds="cds_dt" exclude-result-prefixes="cds">
          <!-- Identity transfrom - just copy what doesn't need changing -->
          <xsl:template match="@* | node()">
              <xsl:copy>
                  <xsl:apply-templates select="@* | node()"/>
              </xsl:copy>
          </xsl:template>
      
          <!-- a rule for what does need changing -->
          <!-- Change all Target nodes whose parent has a child of Name equal to ThisOne -->
          <xsl:template match="/A/B[Name='ThisOne']/Target">
              <Target>xyz</Target>
          </xsl:template>
      </xsl:stylesheet>
      

      【讨论】:

      • 谢谢。这当然更简洁,但并不能消除替换整个元素的必要性,而不仅仅是文本。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多