Yalmar
Yalmar

Reputation: 435

change attribute value depending on parent's attribute value

I have a large number of html files with the following structure:

<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
    <title>t</title>
  </head>
  <body>
    <div class="a">
      <div class="b">
        <div class="b1" type="t23">b11</div>
        <div class="b2" type="t45">b21</div>
      </div>
      <div class="a">
        <div class="c">
          <div class="b1" type="t67">b12</div>
          <div class="b2" type="t89">b22</div>
        </div>
      </div>
    </div>
  </body>
</html>

I would like to do the following transformations:

  1. if node div class="b1" has parent div class="c" then rename child attribute value to c1 (div class="c1")
  2. if node div class="b2" has parent div class="c" then rename child attribute value to c2 (div class="c2")
  3. keep other attributes and text nodes

The output I am trying to get is the following:

<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
    <title>t</title>
  </head>
  <body>
    <div class="a">
      <div class="b">
        <div class="b1" type="t23">b11</div>
        <div class="b2" type="t45">b21</div>
      </div>
      <div class="a">
        <div class="c">
          <div class="c1" type="t67">b12</div>
          <div class="c2" type="t89">b22</div>
        </div>
      </div>
    </div>
    </div>
  </body>
</html>

I am using the following shell script:

xsltproc a.xslt a.html > b.html

where a.xslt as follows:

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

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

 <xsl:template match="@class">
  <xsl:attribute name="class">
   <xsl:choose>
    <xsl:when test=". = 'b1'">
      <xsl:text>c1</xsl:text>
    </xsl:when>
    <xsl:when test=". = 'b2'">
      <xsl:text>c2</xsl:text>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="." />
    </xsl:otherwise>
   </xsl:choose>
  </xsl:attribute>
 </xsl:template>

</xsl:stylesheet>

However this xslt changes all class="b1" to class="c1" and all class="b2" to class="c2", disregarding the parent attribute.

Do you have any suggestions on how to solve this problem?

Upvotes: 0

Views: 548

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 117100

Why don't you do exactly what you say you want to do:

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

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

<!-- if node div class="b1" has parent div class="c" then rename child attribute value to c1 (div class="c1") -->
<xsl:template match="div[@class='c']/div[@class='b1']/@class">
    <xsl:attribute name="class">c1</xsl:attribute>
</xsl:template>

<!-- if node div class="b2" has parent div class="c" then rename child attribute value to c2 (div class="c2") -->
<xsl:template match="div[@class='c']/div[@class='b2']/@class">
    <xsl:attribute name="class">c2</xsl:attribute>
</xsl:template>

</xsl:stylesheet>

Upvotes: 1

Related Questions