2

I'm attempting to clean up a file with arbitrary element names that looks like:

<root>
    <nodeone>
        <subnode>with stuff</subnode>
    </nodeone>
    <nodeone>
        <subnode>with other stuff</subnode>
    </nodeone>
    <nodeone>
        <subnode />
    </nodeone>
</root>

into a file that looks like:

<root>
    <nodeone>
        <subnode>with stuff</subnode>
    </nodeone>
    <nodeone>
        <subnode>with other stuff</subnode>
    </nodeone>
</root>

You can see that all of "nodeone" that had the empty children disappeared. I've used a solution that removes the empty <subnode>, but keeps the <nodeone>. The desired result is that both of those elements are removed.

My current attempt at a solution (which does precisely nothing) is:

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

    <xsl:template match="node()|@*">
        <xsl:call-template name="backwardsRecursion">
            <xsl:with-param name="elementlist" select="/*/node/*[normalize-space()]"/>
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="backwardsRecursion">
        <xsl:param name="elementlist"/>

        <xsl:if test="$elementlist">
            <xsl:apply-templates select="$elementlist[last()]"/>

            <xsl:call-template name="backwardsRecursion">
                <xsl:with-param name="elementlist" select="$elementlist[position() &lt; last()]"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

    <xsl:template match="/*/node/*[normalize-space()]">
          <xsl:value-of select="."/>
    </xsl:template>
</xsl:stylesheet>

XSLT is not something I use terribly often, so I'm a bit lost.

1
  • 1
    This is a well-asked question in my opinion. It is clear that you have tried to find a way to call templates recursively, as you would in other programming languages. Yet, the beauty of XSLT (if there is such a thing) is that it applies templates recursively by default and the code you write usually stops or alters the recursion process - as kjhughes shows below. Commented Feb 12, 2016 at 20:42

1 Answer 1

2

Start with identity transformation,

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

and add a template to squelch elements without signficant, non-space-normalized string values,

  <xsl:template match="*[not(normalize-space())]"/>

and you'll get the results you seek.

Altogether:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*[not(normalize-space())]"/>

</xsl:stylesheet>
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.