0
votes

Is it possible to replace the call-template statement in the following stylesheet with a apply-statement? So that the structure of the templates are nearly the same. With structure I mean that I have a xpath to select a element form the source xml e.g. /shiporder/address/city and I have a target xpath for my output xml e.g. /root/Address/Country then I step reverse through the source path. All /shiporder/address/city goes under Country all /shiporder/address goes under Address and the root shiporder become the tag root.

Source XML:

<shiporder>
  <shipto>orderperson1</shipto>
  <shipfrom>orderperson2</shipfrom>
  <address>
  <city>London</city>
  </address>
  <address>
  <city>Berlin</city>
  </address>
</shiporder>

Stylesheet:

<xsl:template match="/">
        <xsl:apply-templates select="shiporder"/>
  </xsl:template>

 <xsl:template match="/shiporder">
    <root>
        <xsl:apply-templates select="address/city"/>
        <xsl:call-template name="Identity" />
    </root>
 </xsl:template>


<xsl:template name="Identity">
    <Identity>
        <xsl:call-template name="Name" />
    </Identity>
</xsl:template>

<xsl:template name="Name">
    <Name>
        <xsl:apply-templates select="/shiporder/shipto"/>
    </Name>
</xsl:template>

<xsl:template match="/shiporder/shipto">
    <Last>
        <xsl:apply-templates select="text()"/>
    </Last>
</xsl:template>


 <xsl:template match="/shiporder/address/city">
    <Country>
        <xsl:apply-templates select="text()"/>
    </Country>
 </xsl:template>
2
Can you explain why you chose to use <xsl:call-template> in the first place?Tomalak
I don't get your question. I want to use apply instead of call.StellaMaris
I know. I want to understand why you used "call", so that maybe I can help to clarify a mistake in your thinking.Tomalak
Because I had no better idea to define a template where I can write a node to the output and apply the next template and pass through the current node to that output without using the mode attribute.StellaMaris
Ah. Well, you can output nodes with any kind of nesting in any kind of template. No need to start new templates per nesting level or anything like that. Compare stackoverflow.com/q/4478045/18771Tomalak

2 Answers

2
votes

you can use the following:

<?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" indent="yes" encoding="UTF-8"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/shiporder">
        <root>
            <xsl:apply-templates select="address/city"/>
            <xsl:apply-templates select="shipto"/>
        </root>
    </xsl:template>

    <xsl:template match="shipto">
        <Identity>
            <Name>
                <Last><xsl:value-of select="."/></Last>
            </Name>
        </Identity>
    </xsl:template>

    <xsl:template match="/shiporder/address/city">
        <Country>
            <xsl:value-of select="."/>
        </Country>
    </xsl:template>

</xsl:stylesheet>
1
votes

Generally speaking, <xsl:call-template name="..."/> can be turned into a <xsl:apply-templates select="current()" mode="..."/> and <xsl:template match="node()" mode="..."/> (as long as this mode is not used anywhere else).

But there, the upvoted answer is way more suited.