4

I'm struggling with trying to test to see if an element exists. If it doesn't, I'd like to add in a default value. Here's my XML

<records>
  <record>
    <InstanceData>
      <instance>
        <FirstName>Johhny</FirstName>
        <LastName>Jenkins</LastName>
        <AlbumCount>3</AlbumCount>
      </instance>
    </InstanceData>
  </record>
  <record>
    <InstanceData>
      <instance>
        <FirstName>Art</FirstName>
        <LastName>Tatum</LastName>
        <AlbumCount>7</AlbumCount>
      </instance>
    </InstanceData>
  </record>
  <record>
    <InstanceData>
      <instance>
        <FirstName>Count</FirstName>
        <LastName>Basie</LastName>
      </instance>
    </InstanceData>
  </record>
</records>

I'd like to be able to copy over existing values and set any record without the Album Count element to <AlbumCount>0</AlbumCount>. This is the xslt I've been working with but I think I'm some way off the mark.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="1.0"> 
  <xsl:template match="Records">
    <xsl:for-each select="node()">
      <xsl:choose>
        <xsl:when test="name()='AlbumCount'">
          <xsl:element name="AlbumCount">
            <xsl:choose>
              <xsl:when test="name()='AlbumCount'">
                <xsl:copy-of select=".">
                </xsl:copy-of>
              </xsl:when>
              <xsl:otherwise>
                <AlbumCount>0</AlbumCount>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:element>
        </xsl:when>
        <xsl:otherwise>
          <xsl:copy-of select=".">
          </xsl:copy-of>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

Thanks for looking.

1
  • 1
    What output are you currently getting? Commented Jul 11, 2011 at 10:35

2 Answers 2

8

Try this:

<?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" omit-xml-declaration="no"/>

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

<xsl:template match="instance[not(AlbumCount)]">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
        <AlbumCount>0</AlbumCount>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>   

Start with the identity transformation, then just handle the exception differently.

Sign up to request clarification or add additional context in comments.

1 Comment

@Dimitre - taa for the big up!
3

You test for the existance of an element simply with the elements name, for example:

<xsl:if test="not(AlbumCount)">
  <AlbumCount>0</AlbumCount>
</xsl:if>

The simpler way to do what you want is to use the standard copy template combined with a special rule for places where AlbumCount elements need adding:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:output method="xml" indent="yes"/>

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

  <!-- Special template to add AlbumCount elements where required -->
  <xsl:template match="records/record/InstanceData/instance">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
      <xsl:if test="not(AlbumCount)">
        <AlbumCount>0</AlbumCount>
      </xsl:if>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

1 Comment

@Kragen I'm bowing to Dimitre's request but still a big thanks for coming up with a working solution!

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.