XSL修改另一个元素的元素值

时间:2018-09-28 12:20:10

标签: xml xslt xslt-1.0 xslt-2.0

我希望能够从元素B的模板修改元素A的值

XML输入

<Parent>
   <Elem1 Attr="Something" OtherAttr="Other">ExistingValue</Elem1>
   <Elem2 Attr="SomethingElse" />
</Parent>

XSL

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

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

<xsl:template match="Elem1">
   <!-- SOMEHOW MODIFY HERE VALUE OF ELEM2 -->
</xsl:template>
</xsl:stylesheet>

预期的XML输出

<Parent>
 <Elem1 Attr="Something" OtherAttr="Other">ExistingValue</Elem1>
 <Elem2 Attr="SomethingElse">Value from elem1</Elem2>
</Parent>

2 个答案:

答案 0 :(得分:1)

您无法在XSLT中“修改”内容。您的样式表将一个XML文档作为输入,并生成另一个XML文档作为输出。最好将样式表考虑为顺序编写输出,访问在构造每个结果元素时需要构造的每个输入部分。唯一可以设置元素E值的时间是在编写元素E时。(这是对所发生情况的过度时间导向的描述,但这是一个有用的心理模型。)

在您的示例中,用于设置Elem2值的代码通常属于Elem2的模板规则。

答案 1 :(得分:1)

这是一个主意。
               

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

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

  <xsl:apply-templates select="//Elem2" mode="outElem2">
    <xsl:with-param name="Elem1Attr" select="@Attr"/>
    <!-- You could also pass the value from Elem1 here. -->
  </xsl:apply-templates>
</xsl:template>

<!-- Suppress Elem2-->
<xsl:template match="Elem2"/>

<!--**** outElem2 mode. -->  
<xsl:template match="node() | @*" mode="outElem2">
  <xsl:param name="Elem1Attr"/>
  <xsl:copy>
    <xsl:apply-templates select="node() | @*" mode="outElem2">
      <xsl:with-param name="Elem1Attr" select="@Attr"/>
    </xsl:apply-templates>
  </xsl:copy>
</xsl:template>

<xsl:template match="Elem2" mode="outElem2">
  <xsl:param name="Elem1Attr"/>
  <xsl:copy>
    <!-- Output the attributes. -->
    <xsl:apply-templates select="@*" mode="outElem2"/>

    <xsl:choose>
      <xsl:when test="$Elem1Attr = 'Something'">
        <xsl:value-of select="'Value from elem1'"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="'Something else'"/>
      </xsl:otherwise>
    </xsl:choose> 
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>