mipnw
mipnw

Reputation: 2325

XSLT: remove a child when a parent has an attribute

I wish to remove element d and comment <!-- d --> when the parent has attribute c="string1"

Input:

<a>
 <b c="string1">
   <!-- d -->
   <d>
     <e/>
   </d>
   <f/>
 </b>

 <b c="string2">
   <!-- d -->
   <d>
     <e/>
   </d>
   <f/>
 </b>
</a>

Desired output:

<a>
 <b c="string1">
   <f/>
 </b>

 <b c="string2">
   <!-- d -->
   <d>
     <e/>
   </d>
   <f/>
 </b>
</a>

XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

   <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

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

   <!-- Those templates do not work -->
   <xsl:template match="d[???]" />
   <xsl:template match="comment()="d" />
</xsl:stylesheet>

Upvotes: 0

Views: 107

Answers (2)

michael.hor257k
michael.hor257k

Reputation: 116982

Here's one way you could look at it:

<xsl:template match="b[@c='string1']/d" />
<xsl:template match="b[@c='string1']/comment()[.=' d ']" />

Or, if you prefer:

<xsl:template match="b[@c='string1']">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()[not(self::d or self::comment()[.=' d '])]"/>
    </xsl:copy>
</xsl:template>

Note that the value of the comment in the given example is actually " d " i.e. the character "d" surrounded by spaces.

Upvotes: 1

mipnw
mipnw

Reputation: 2325

Found a solution. These two xsl:templates work.

<xsl:template match="d[ancestor::b[@c='string1']]" />
<xsl:template match="comment()[contains(.,'d') and ancestor::b[@c='string1']]" />

I would prefer not using contains(.,'d') but an equality expression on the text of the comment, but I don't know how to write that expression.

Upvotes: 0

Related Questions