Papouche Guinslyzinho
Papouche Guinslyzinho

Reputation: 5448

xslt test if an attribute exist

I have this following xslt. I notice that sometimes the element name 'tuple' has an attribute. I want to remove the attribute and add it as an Element. I added a test to verify if 'tuple' has an attribute but it returns a blank 'ecatalogue' element.

<?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" version="1.0" encoding="UTF-8"
        indent="yes" />
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="atom">
        <xsl:element name="{@name}">
            <xsl:apply-templates />
        </xsl:element>
    </xsl:template>
    <xsl:template match="table">
        <xsl:element name="{@name}">
            <xsl:apply-templates />
        </xsl:element>
    </xsl:template>
    <!--this test doesn't work properly -->
    <xsl:template match="tuple">
      <xsl:choose>
        <xsl:when test="@name">
             <xsl:apply-templates />
        </xsl:when>
        <xsl:otherwise>
            <!-- nothing to do
            the node should stay the same
        -->
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>
    <!-- end test -->
</xsl:stylesheet>

result I had with this template above.

<ecatalogue>

</ecatalogue>

https://gist.github.com/guinslym/5ce47460a31fe4c4046b

Upvotes: 2

Views: 4866

Answers (2)

michael.hor257k
michael.hor257k

Reputation: 116959

I notice that sometimes the element name 'tuple' has an attribute. I want to remove the attribute and add it as an Element. I added a test to verify if 'tuple' has an attribute

This is definitely not the best approach when working with XSLT. You want to transform the attribute, not its parent tuple element - so your template should match the attribute directly, for example:

<xsl:template match="tuple/@*">
    <xsl:element name="{name()}">
        <xsl:apply-templates />
    </xsl:element>
</xsl:template>

No tests are required here: if the attribute exists, the template will match it and process it; if not, the template will not be applied at all.

--

Note: the above is assuming you want to transform the attribute into a child element of tuple, sibling to the other, already existing, children.Your post is not quite clear on that point.

Upvotes: 4

matthias_h
matthias_h

Reputation: 11416

With the following adjustments to your template matching tuple

<xsl:template match="tuple">
  <xsl:choose>
    <xsl:when test="@name">
      <tuple>
        <xsl:element name="{@name}"/>
        <xsl:apply-templates />
      </tuple>
    </xsl:when>
    <xsl:otherwise>
      <xsl:copy>
        <xsl:apply-templates />
      </xsl:copy>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

all tuple nodes without a name attribute are copied:

<xsl:otherwise>
  <xsl:copy>
    <xsl:apply-templates />
  </xsl:copy>
</xsl:otherwise>

and in case a tuple has a name attribute, the tuple is written without an attribute, the attribute added as element (without any value as it's not clear if it should have any value) and the child nodes copied:

<xsl:when test="@name">
  <tuple>
    <xsl:element name="{@name}"/>
    <xsl:apply-templates />
  </tuple>
</xsl:when>

Part of the input XML as example:

<tuple name="ObjManufacturerRef">
  <NamOrganisation>Unknown;:;Inconnu</NamOrganisation>
  <NamOrganisationAcronym>Unknown</NamOrganisationAcronym>
  <AddPhysCountry>Unknown</AddPhysCountry>
</tuple>

results in:

<tuple>
  <ObjManufacturerRef/>
  <NamOrganisation>Unknown;:;Inconnu</NamOrganisation>
  <NamOrganisationAcronym>Unknown</NamOrganisationAcronym>
  <AddPhysCountry>Unknown</AddPhysCountry>
</tuple>

Saved example: http://xsltransform.net/nc4NzQq/1 with an added <xsl:strip-space elements="*"/> to remove whitespace.

Upvotes: 2

Related Questions