views:

370

answers:

1

I thought this ought to be simple to find, yet after some searching I found this might be nice to define clearly.

In my XSD I've defined an enum, derived from string. In a complex type I've defined and attribute that refers to this enum, with a default value.

In my XSL I wish to display the default value of this attribute for elements whose attribute is not explicitly set.

The XSD:

<xs:complexType name="foo">
    <xs:attribute name="bar" type="responsecodes:barType" default="default"/>
</xs:complexType>

<xs:simpleType name="barType">
    <xs:restriction base="xs:string">
     <xs:enumeration value="default">
      <xs:annotation>
       <xs:documentation xml:lang="en-us">Default bar.</xs:documentation>
      </xs:annotation>
     </xs:enumeration>
     <xs:enumeration value="chocolate">
      <xs:annotation>
       <xs:documentation xml:lang="en-us">A chocolate ...bar</xs:documentation>
      </xs:annotation>
     </xs:enumeration>
    </xs:restriction>
</xs:simpleType>

The XML:

....
<foo/>
<foo bar="default"/>
<foo bar="chocolate"/>
....

I'd expect the XSL to be: (more or less)

<ol>
<xsl:for-each select="/foo">
    <li>BarType: '<xsl:value-of select="@bar" />'</li>
</xsl:for-each>
</ol>

Now when I display this style XML file, the value of the 'bar' attribute is empty for the non-specified value, while I'd wish to display (or select on) the default value.

Now:

  1. BarType: ''
  2. BarType: 'default'
  3. BarType: 'chocolate'

Desired:

  1. BarType: 'default'
  2. BarType: 'default'
  3. BarType: 'chocolate'

Now this ought to be quite simple, no?

+1  A: 

Maybe I'm overgeneralizing, but if you want to load the default from the schema, you would need something along the lines of this:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs"
>

  <xsl:variable name="schema" select="
    document('responsecodes.xsd')
  " />
  <xsl:variable name="DefaultBar" select="
    $schema//xs:complexType[@name='foo']/xs:attribute[@name='bar']/@default
  " />

  <xsl:template match="foo">
    <li>
      <xsl:text>BarType: '</xsl:text>
      <xsl:choose>
        <xsl:when test="@bar">
          <xsl:value-of select="@bar" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$DefaultBar" />
        </xsl:otherwise>
      </xsl:choose>
      <xsl:text>'</xsl:text>
    </li>
  </xsl:template>
</xsl:stylesheet>
Tomalak
Thanks for the reply. Looks like quite a bit of 'work' for a value that is so easily defined at XSD level. I understand the reason for a non-value not to be displayed, but I'd really expect an easier way to fall back to the default value. (something like xsl:value-of-or-default)As you might have guessed I'm quite new to XSL, I've barely scatched the surface.
Robert Sirre
XSLT is not quite as integrated with XML Schema as you might think. It is an XML transformation language, it can look at Schema as yet another XML document. This is what I did here. XSLT does not care whether your XML is valid against a schema or not, all it needs is well-formedness. There is no `xsl:value-of-or-default`.
Tomalak
I understand the method you supplied.I just guessed that as the XSL 'found' the attribute value via XPath selection, and this needs the correct namespace mapping, It would be more aware of the definitions and restriction imposed by the XSD.Do you in general agree with me that this is not a strange question to ask?
Robert Sirre
If that helps. ;-) XSLT has just not been designed as a Schema-aware XML validation helper. Maybe XSLT 2.0 has some more support for that (I don't know 2.0 too well), but with 1.0 the above is close as it gets. I could think of a way to generalize default-value-fetching some more, but it will always stay in that ballpark.
Tomalak