Domanda

I will precede this with the fact that I am new to XSLT (1.0 in this case) and have had little luck on getting this resolved on my own. I have the following XML:

<Root>
<Info>
    <Feature>SEA</Feature>
    <Sequence>10</Sequence>
    <Value>Y</Value>
</Info>
<Info>
    <Feature>SEA</Feature>
    <Sequence>20</Sequence>
    <Value>Y</Value>
</Info>
<Info>
    <Feature>TEL</Feature>
    <Sequence>10</Sequence>
    <Value>N</Value>
</Info>
<Info>
    <Feature>TEL</Feature>
    <Sequence>20</Sequence>
    <Value>Y</Value>
</Info>
<Info>
    <Feature>TEL</Feature>
    <Sequence>35</Sequence>
    <Value>Y</Value>
</Info>
</Root>

I need to evaluate all the Features equal to SEA against all the Features equal to TEL where the Sequence is the same. The output would include both the original SEA value, and the TEL value.

Output request is:

<Root>
<Info>
    <Feature>SEA</Feature>
    <Sequence>10</Sequence>
    <SEAValue>Y</SEAValue>
    <TELValue>N</TELValue>
</Info>
<Info>
    <Feature>SEA</Feature>
    <Sequence>20</Sequence>
    <SEAValue>Y</SEAValue>
    <TELValue>Y</TELValue>  
</Info>
</Root>
È stato utile?

Soluzione

The simplest and most efficient way to do joins in XSLT is with a key. Declare a key:

<xsl:key name="k" match="Info[Feature='TEL']" use="Sequence"/>

and then you can do

<xsl:for-each select="Info[Feature='SEA']">
  <xsl:copy-of select="Feature"/>
  <xsl:copy-of select="Sequence"/>
  <SEAValue><xsl:value-of select="value"/></SEAValue>
  <TELValue><xsl:value-of select="key('k', Sequence)/Value"/></TELValue>
</xsl:for-each>

Altri suggerimenti

You may try this key based solution:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" indent="yes"/>
    <xsl:key name="kSequence" match="Info" use="Sequence"/>

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

    <xsl:template match="Info/Value" >
        <xsl:element name="{../Feature}Value" >
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="/*" >
        <xsl:copy>
            <xsl:for-each select="//Info[count( . | key('kSequence', Sequence)[1])=1]" >
                <xsl:variable name="is" select="key('kSequence', current()/Sequence)" />
                <xsl:if test="$is[Feature = 'SEA'] and $is[Feature = 'TEL']" >
                    <xsl:copy>
                        <xsl:apply-templates select="$is[Feature = 'SEA']/*" />
                        <xsl:apply-templates select="$is[Feature = 'TEL']/Value" />
                    </xsl:copy>
                </xsl:if>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top