Search code examples
xmlxsltxslt-2.0

xslt how to remove the parent tag and change attributes of a child tag in an xml doc


I have an example xml like below

<map>
<topicref href="disclaimer_PUBLIC.dita" outputclass="Top">
    <fig>
      <image href="">
        qw
      </image>
      <image href="">
        q1
      </image>
    </fig>
  </topicref>
  <topicref href="DocID030323.xml">
    <fig>
      <image href="">
        qw
      </image>
      <image href="">
        q1
      </image>
    </fig>
  </topicref>
</map>

Now here I want to remove the tag <fig> and add attribute width=5cm to the underlying image tag whenever the topicref outputclass="Top" . I want the output as below:

<topicref href="../Topics/dita" outputclass="Top">

      <image href="" width="5cm">
        qw
      </image>
      <image href="" width="5cm">
        q1
      </image>

  </topicref>
  <topicref href="DocID030323.dita">
      <fig class="- topic/fig ">
         <image href=""
        qw
      </image>
         <image href="">
        q1
      </image>
      </fig>
  </topicref>

I am trying to achieve this but can only do 1 operation at a time in an xslt. how to combine both operations?

when I use

<xsl:template match="topicref[@outputclass='Top']/fig" >
      <xsl:apply-templates select="node()"/>

  </xsl:template> 

the fig element is removed but can't change the attribute values.

and when I use

<xsl:template match="topicref[@outputclass='Top']/fig/image" >
    <xsl:copy>
    <xsl:apply-templates select="@*"/>
    <xsl:attribute name="width">
      <xsl:value-of select="'2.5'"/>
    </xsl:attribute>
      <xsl:apply-templates select="node()"/>
    </xsl:copy>

  </xsl:template>

even the fig element is copied.I want to perform both operations in 1 xslt. Please help.


Solution

  • The following XSLT

      <xsl:template match="topicref[@outputclass='Top']/fig">
        <xsl:apply-templates></xsl:apply-templates>
    </xsl:template>
    <xsl:template match="topicref[@outputclass='Top']/fig/image" >
        <xsl:copy>
    
            <xsl:copy-of select="@*"/>
            <xsl:attribute name="width">
                <xsl:value-of select="'2.5'"/>
            </xsl:attribute>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    
    </xsl:template>
    <xsl:template match="*">
        <xsl:copy>
            <xsl:copy-of select="@*"></xsl:copy-of>
            <xsl:apply-templates></xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
    

    Produces

    <?xml version="1.0" encoding="UTF-8"?><map>
    <topicref href="disclaimer_PUBLIC.dita" outputclass="Top">
    
            <image href="" width="2.5">
                qw
            </image>
            <image href="" width="2.5">
                q1
            </image>
    
    </topicref>
    <topicref href="DocID030323.xml">
        <fig>
            <image href="">
                qw
            </image>
            <image href="">
                q1
            </image>
        </fig>
    </topicref>
    </map>
    

    Hope this helps