We have (perhaps unusually formatted) XML files that (very simplified) look like this:
<Contacts>
<Contact>
<Private>
<Name>John Doe</Name>
<Address>Somewhere1</Address>
...
</Private>
</Contact>
<Contact>
<Business>
<Name>John Business</Name>
<Address>Somewhere2</Address>
<BusinessAddress>Somewhere3</BusinessAddress>
...
</Business>
</Contact>
...
</Contacts>
In reality, we have several dozens of different types of "Contact" nodes with many more attributes, several of which however are common between all types...
We currently use a stylesheet to format the XML file that repeats the formatting for all common attributes for each type of "Contact" node:
<!-- ... loads of prologue code -->
<xsl:for-each select="Contacts/Contact/.">
<xsl:choose>
<xsl:when test="Private">
<!-- code to format each and every attribute of the current
"Contact" element, e.g.: -->
<td class="header">Private Contact</td>
<td class="detail"><xsl:value-of select="./Name"/></td>
<!-- ... -->
</xsl:when>
<xsl:when test="Business">
<!-- code to format each and every attribute of the current
"Contact" element, e.g.: -->
<td class="header">Business Contact/<td>
<td class="detail"><xsl:value-of select="./Name"/></td>
<!-- ... -->
</xsl:when>
<!-- ... -->
</xsl:choose>
</xsl:for-each>
But we're getting more and more <Contact>
types with more and more attributes, resulting in a mile-long stylesheet, so I want to simplify the stylesheet as follows:
<!-- ... loads of prologue code -->
<xsl:for-each select="Contacts/Contact/.">
<!-- loads of formatting stuff common to each "Contact" type, but with
some wording that's "Contact" type dependant, e.g. -->
<td class="header">**????** Contact</td>
<td class="detail"><xsl:value-of select="./Name"/></td>
<xsl:choose>
<xsl:when **????** = "Private">
<xsl:variable name="contactWhen">off</xsl:variable>
</xsl:when>
<xsl:when **????** = "Business">
<xsl:variable name="contactWhen">office</xsl:variable>
</xsl:when>
<!-- ... -->
</xsl:choose>
<td class="header">Contact/<td>
<td class="detail">Only during $contactWhen hours</td>
<xsl:choose>
<xsl:when test="Private">
<!-- code to format attributes specific for the current "Contact" -->
</xsl:when>
<xsl:when test="Business">
<!-- code to format attributes specific for the current "Contact" -->
</xsl:when>
<!-- ... -->
</xsl:choose>
</xsl:for-each>
My excuses if there are any typo's or syntax errors in above code samples, but I'm not very intimate to XSLT syntax and most of above code was hand-crafted for the sake of the example...
My problem is that I'm not able to get the name value of the node under Contact
, in this example Private
or Business
. I've tried using all variations I could think of, both of value-of select=
and of simply select= (a.o. "", ".", "./."
, Contacts/Contact
, Contacts/Contact/.
, [local-]name()
and even Field[@name='.']
).
Some attempts produce errors, some result in an empty string, some return the name of the parent node, i.e. Contact
, and some return the values of all subordinate attributes (without attribute names though) as a single string... :-(
What should I code for **????**
to test for the name value of the current node, and eventually assign some variable(s) a value based on the results of this test?
Thanks for any assistance,
Juul
Hi,
Thanks for the valuable input and I'll definitely consider converting this and some other similar) stylesheet(s) to use templates, but for now I'm under pressure to deliver this project.
I tried all 3 suggestions in the 'for-each' loop and just before the 'choose', but all 3 fail:
<td class="content2" colspan="2"><xsl:value-of select="ancestor::Record/child::*[1]name"/></td>
fails with XML error: expected 'EOF' found 'name'
<td class="content2" colspan="2"><xsl:value-of select="name()"/></td>
returns "Contact", not the name of the first child name
<xsl:variable name="contactType">
<xsl:choose>
<xsl:when test="Private">Private</xsl:when>
<xsl:when test="Business">Business</xsl:when>
</xsl:choose>
<td class="content2" colspan="2"><xsl:value-of select="$contactType"/></td>
</xsl:variable>
fails with XML error: reference to variable 'contactType' cannot be resolved. The variable may not be defined or it may not be in scope.
Can this behaviour be caused by having these constructs in inline code instead of in a template.
Please advise,
Juul