Here just to explain, I am inserting a simplified version of
the original
xml and xsl:
<Quote>
<Info>
<attribute>
<name>
BILL_TO_ADDRESS3</name>
<atomicValue>PO BOX 1234</atomicValue>
</attribute>
<attribute>
<name>
BILL_TO_ADDRESS2</name>
<atomicValue>MEDICAL CENTER</atomicValue>
</attribute>
<attribute>
<name>
PO_NUMBER</name>
<atomicValue>123456</atomicValue>
</attribute>
</Info>
</Quote>
<?xml version = "1.0" encoding = "UTF-8"?>
<xsl:transform xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version =
"1.0">
<xsl:template match = "Quote">
<xsl:text disable-output-escaping="yes"><!DOCTYPE Order></xsl:text>
<xsl:element name = "Order">
<xsl:element name ="Info">
<xsl:apply-templates mode = "Attribs" select = "/Quote/Info"/>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template mode = "Attribs" match = "attribute">
<xsl:element name="BILL_TO_ADDRESS2">
<xsl:value-of select="attribute/atomicValue[../name='BILL_TO_ADDRESS2']"/>
</xsl:element>
<xsl:element name="PO_NUMBER">
<xsl:value-of select="attribute/atomicValue[../name='PO_NUMBER']"/>
</xsl:element>
</xsl:template>
</xsl:transform>
I guess I could have used a common template to copy all name nodes and their
atomicvalues to the output tree, but that would copy all attributes from the
source in the output, which I do not want e.g. the above snippet excludes
attribute with name BILL_TO_ADDRESS3 that is present in the source xml.
Also you will see that I need only the atomicvalues in the output xml. So
the way the logic gets to them is through the name nodes i.e. xsl:value-of
select "the atomicvalue for the node whose name is 'BILL_TO_ADDRESS2'". It
seems that the logic is failing as the processor finds that the values of
the name nodes are '<newline>BILL_TO_ADDRESS2' which hence does not match.
How can I achieve these objectives by using templates?
How about replacing your mode="Attribs" template with:
<xsl:template mode = "Attribs" match = "attribute">
<xsl:call-template name="atomicValue">
<xsl:with-param name="AVname" select="'BILL_TO_ADDRESS2'" />
</xsl:call-template>
<xsl:call-template name="atomicValue">
<xsl:with-param name="AVname" select="'PO_NUMBER'" />
</xsl:call-template>
</xsl:template>
and adding:
<xsl:template name="atomicValue">
<xsl:param name="AVname" select="''" />
<xsl:element name="{$AVname}">
<xsl:value-of
select="attribute/atomicValue[normalize-space(../name)=$AVname]"/>
</xsl:element>
</xsl:template>
The above is a little more modularized; I think it addresses your reluctance
to use normalize-space() "everywhere". You've packaged it inside a
single template.
There's always the following, although it sounds like you don't like
repeating normalize-space():
<xsl:template mode = "Attribs" match = "attribute">
<BILL_TO_ADDRESS2>
<xsl:value-of
select="attribute/atomicValue[normalize-space(../name)='BILL_TO_ADDRESS2']"/>
</BILL_TO_ADDRESS2>
<PO_NUMBER>
<xsl:value-of
select="attribute/atomicValue[normalize-space(../name)='PO_NUMBER']"/>
</PO_NUMBER>
</xsl:template>
Lars
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list