有条件地修改多个同名子代中的文本

时间:2018-10-11 03:19:24

标签: xslt

我正在尝试有条件地修改某些XML的内容。 Am元素具有多个名称相同的子代,我想根据文本内容对其进行修改。例如,我有以下XML:

<first>
  <second>
    <third>alice</third>
    <third>bob</third>
    <third>charlie</third>
  </second>
</first>

我想转化为:

<first>
  <second>
    <third>xavier</third>
    <third>yvonne</third>
    <third>charlie</third>
  </second>
</first>

我曾经以为下面的xsl可以工作,但是不行(我怀疑有两个原因)。我在做什么错了?

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="UTF-8" omit-xml-declaration="no"/>
<xsl:strip-space elements="*"/>

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

 <xsl:template match="/first/second/third/">
   <xsl:choose>
     <xsl:when test="contains(text(), 'alice')">
       <xsl:text>xavier</xsl:text>
     </xsl:when>
     <xsl:when test="contains(text(), 'bob')">
       <xsl:text>Yvonne</xsl:text>
   </xsl:when>
   <xsl:otherwise>
     <xsl:value-of select="text()"/>
   </xsl:otherwise>
   </xsl:choose>
 </xsl:template>

</xsl:stylesheet>

1 个答案:

答案 0 :(得分:1)

您做错了两件事:

  • 此XPath /first/second/third/的末尾有一个斜杠。从语法上说,在XPath的末尾加斜杠是不合法的,并且您在这里不需要一个斜杠。
  • 您有一个模板,该模板应该与third个元素匹配(基本上是它们曾经的元素的替代品),但是您没有复制这些元素。您只是将它们替换为文本,这意味着您将得到如下结果:
<first>
  <second>xavieryvonnecharlie</second>
</first>

为了使您能够尝试工作,将模板修改为此就足够了:

<xsl:template match="/first/second/third">
  <xsl:copy>
    <xsl:choose>
      <xsl:when test="contains(text(), 'alice')">
        <xsl:text>xavier</xsl:text>
      </xsl:when>
      <xsl:when test="contains(text(), 'bob')">
        <xsl:text>Yvonne</xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="text()"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:copy>
</xsl:template>

但是,可以通过使模板与您要替换的文本节点匹配来更加干净地完成此操作:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" encoding="UTF-8" omit-xml-declaration="no"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="third/text()[. = 'alice']">xavier</xsl:template>

  <xsl:template match="third/text()[. = 'bob']">yvonne</xsl:template>

</xsl:stylesheet>

在示例输入上运行时,结果为:

<first>
   <second>
      <third>xavier</third>
      <third>yvonne</third>
      <third>charlie</third>
   </second>
</first>