Yalmar
Yalmar

Reputation: 435

xslt Rename node's attribute value depending on ancestor's attribute value

I have a large number of html files like the following:

<html>
  <body>
    <div class="a">aaa
      <div class="a1">a1a1a1</div>
      <div class="a2">a2a2a2</div>
      <div class="a2">a3a3a3</div>
    </div>
    <div class="v u">bbb
      <div class="x">xxx</div>
      <div class="y">yyy</div>
      <div class="z">z1z1z1
        <div class="w">www1</div>
        <div class="w">www2</div>
        <div class="w">www3</div>
      </div>
      <div class="z">z2z2z2
        <div class="w">www4</div>
        <div class="w">www5</div>
        <div class="w">www6</div>
      </div>
    </div>
    <div class="i">
      <div class="j">jjj</div>
      <div class="x">
        <div class="k">
          <div class="w">www7</div>
          <div class="w">www8</div>
        </div>
      </div>
    </div>
  </body>
</html>

The classes x, y, z, and w can occur any number of times and with any div throughout the html.

There is one and only one div class="v u"

I would like to:

  1. Rename the classes x, y, z, and w to b1, b2, b3, and b4 respectively if and only if any ancestor of that node is div class="v u"
  2. Rename div class="v u" to div class="b"

The result would then be:

<html>
  <body>
    <div class="a">aaa
      <div class="a1">a1a1a1</div>
      <div class="a2">a2a2a2</div>
      <div class="a2">a3a3a3</div>
    </div>
    <div class="b">bbb
      <div class="b1">xxx</div>
      <div class="b2">yyy</div>
      <div class="b3">z1z1z1
        <div class="b4">www1</div>
        <div class="b4">www2</div>
        <div class="b4">www3</div>
      </div>
      <div class="b3">z2z2z2
        <div class="b4">www4</div>
        <div class="b4">www5</div>
        <div class="b4">www6</div>
      </div>
    </div>
    <div class="i">
      <div class="j">jjj</div>
      <div class="x">
        <div class="k">
          <div class="w">www7</div>
          <div class="w">www8</div>
        </div>
      </div>
    </div>
  </body>
</html>

I have tried the following xslt, that doesn't give me the expected result:

<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()" >
  <xsl:copy>
   <xsl:apply-templates select="@*|node()" />
  </xsl:copy>
 </xsl:template>

 <xsl:template match="div[@class='v u']"> 
  <div class="b">
   <xsl:copy-of select="node()" />
  </div>
 </xsl:template>

 <xsl:template match="div[@class='v u']/div[@class='x']"> 
  <div class="b1">
   <xsl:copy-of select="node()" />
  </div>
 </xsl:template>

 <xsl:template match="div[@class='v u']/div[@class='y']"> 
  <div class="b2">
   <xsl:copy-of select="node()" />
  </div>
 </xsl:template>

 <xsl:template match="div[@class='v u']/div[@class='z']"> 
  <div class="b3">
   <xsl:copy-of select="node()" />
  </div>
 </xsl:template>

 <xsl:template match="div[@class='v u']/div[@class='z']/div[@class='w']"> 
  <div class="b4">
   <xsl:copy-of select="node()" />
  </div>
 </xsl:template>

</xsl:stylesheet> 

I think I understand why it is not giving me the correct result, however I do not seem to find the correct solution.

Upvotes: 0

Views: 41

Answers (1)

Martin Honnen
Martin Honnen

Reputation: 167716

Instead of all those <xsl:copy-of select="node()" /> you need to use <xsl:apply-templates/> or <xsl:apply-templates select="node()"/> to keep the template based processing alive.

Upvotes: 2

Related Questions