按一个子值查找XSL节点,然后更改该节点中的另一个子值

时间:2018-01-29 16:54:17

标签: xml xslt

所以我知道如何基于其中一个子值找到一个节点,但是我如何通过一个子值找到一个xml节点,然后相应地更改该节点的另一个子值。即如果我想通过它的名称标签找到一个狗节点,那么改变它的品种标签。

<dog>
    <name>Fido</name>
    <breed>GSD</breed>
</dog>

应该成为:

<dog>
    <name>Fido</name>
    <breed>Labrador</breed>
</dog>

谢谢, 亚当

3 个答案:

答案 0 :(得分:1)

您可以使用身份模板和替换特定<breed>元素的替换模板:

<?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" omit-xml-declaration="yes" indent="yes"/>

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

  <!-- replaces <breed> elements with specific text content --> 
  <xsl:template match="breed[text()='GSD' and parent::dog[name='Fido']]">
    <breed>Labrador</breed>
  </xsl:template>

</xsl:stylesheet>

<强>输出:

<dog>
    <name>Fido</name>
    <breed>Labrador</breed>
</dog>

答案 1 :(得分:1)

通常情况下,您可以将breed中的dogname&#34; Fido&#34;匹配像这样...

<xsl:template match="dog[name='Fido']/breed">
  <breed>Labrador</breed>
</xsl:template>

但你在评论中说:

  

如果说名称是通过xsltproc传递的变量?

,它将如何处理呢?

在XSLT 1.0中,您无法在match语句中引用变量或参数。您需要使用xsl:choose来检查name(更新后也将品种作为xsl:param传递,但它并非绝对必要)...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:param name="animalName" select="'Fido'"/>
  <xsl:param name="animalBreed" select="'Labrador'"/>

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

  <xsl:template match="breed">
    <xsl:choose>
      <xsl:when test="../name=$animalName">
        <breed><xsl:value-of select="$animalBreed"/></breed>
      </xsl:when>
      <xsl:otherwise>
        <xsl:copy-of select="."/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

在XSLT 2.0中,您只需将匹配更改为dog[name=$animalName]/breed

答案 2 :(得分:0)

因此,通过接受丹尼尔的回答并运行它,这最终给了我最好的解决方案。 (我出于显而易见的原因对代码进行了解释,但它应该足够了)。我仍然说Daniel的答案会有效,因为在大多数情况下它会没问题,但我最终还是需要一种方法来处理在创建问题时我不知道的其他选项。

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


    <xsl:template match="../dog[name = $dog.variable.name]:>
        <xsl:copy-of select="."/>
        <xsl:copy-of select="optionalParams"/>
        .
        .
        .
        <breed>Labrador</breed>
    </xsl:template>