1
votes

I have two XSL variables which holds a data like this First one items

 <values>
  <value>
    12635
  </value>
  <value>
    SD20
  </value>
  <value>
    2404
  </value>
   <value>
    3586877
  </value>
</values>

second one syddata

    <syddata lastUpdated="07.11.2013 11:06 ">
  <data Varenummer="3586877" Varenavn="Liqudffid s" Brand="Georg Jensen" ></data>
  <data Varenummer="12635" Varenavn="tesr" Brand="Kähcddler" ></data>
  <data Varenummer="2404" Varenavn="uhjy" Brand="Pitcfrhstone" ></data>
  <data Varenummer="SD20" Varenavn="sfggh" Brand="dghgh" ></data>
</syddata>

I want to order syddata according to the order of items ..means value field in items are same to Varenummer field in syddata .I want o use this as a key and sort syddata expected output will be like this

    <syddata lastUpdated="07.11.2013 11:06 ">
  <data Varenummer="12635" Varenavn="tesr" Brand="Kähcddler" ></data>
  <data Varenummer="SD20" Varenavn="sfggh" Brand="dghgh" ></data>
  <data Varenummer="2404" Varenavn="uhjy" Brand="Pitcfrhstone" ></data>
  <data Varenummer="3586877" Varenavn="Liqudffid s" Brand="Georg Jensen" ></data>
</syddata>  

I have added my whole XSLT to here ,to get know how the workflow is

<xsl:stylesheet
  version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxml="urn:schemas-microsoft-com:xslt"
  xmlns:XSLTHelper="urn:XSLTHelper"
   xmlns:exslt="http://exslt.org/common"
  xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" 
  exclude-result-prefixes=" msxsl msxml ">
  <xsl:output method="html" omit-xml-declaration="yes"/>
  <xsl:param name="currentPage"/>
  <xsl:template match="/">
        <xsl:variable name="items" select="umbraco.library:Split($textWithPipes, '|')"/>
        <xsl:variable name="syddata" select="XSLTHelper:GenerateData($productids)"/>
  </xsl:template>

</xsl:stylesheet>
2
Is this XSLT 1.0 or 2.0? You have version="2.0" in the stylesheet, but also declarations of the exslt and msxsl extension namespaces which suggest the processor is really 1.0?Ian Roberts
@IanRoberts sorry for that..its XSLT 2.0None
@IanRoberts leaving the actual case for a sec..can you tell me how i need to figure out which is my XSLT processor ..am just using a cms umbraco....or any resources where i can look in to basic details likr theseNone
I'm pretty sure Umbraco uses the standard Microsoft XSLT processor, which is 1.0.Ian Roberts

2 Answers

2
votes

For efficiency I'd start by defining a key (outside any <xsl:template>)

<xsl:key name="dataByNummer" match="data" use="@Varenummer" />

and then the main template could be simply

<xsl:template match="/">
    <xsl:variable name="items" select="umbraco.library:Split($textWithPipes, '|')"/>
    <xsl:variable name="syddata" select="XSLTHelper:GenerateData($productids)"/>

    <xsl:element name="{name($syddata/*)}">
      <!-- copy attributes -->
      <xsl:sequence select="$syddata/*/@*" />
      <!-- copy data in the right order -->
      <xsl:sequence select="
          for $id in $items//value
          return key('dataByNummer', normalize-space($id), $syddata)" />
    </xsl:element>
</xsl:template>

If it were XSLT 1.0 it would be a bit more fiddly because you don't have for expressions in XPath 1.0 and the XSLT 1.0 key function doesn't have the third parameter. But it can still be done in a similar way using nested for-each tags and extra variables

<xsl:template match="/">
    <xsl:variable name="items" select="umbraco.library:Split($textWithPipes, '|')"/>
    <xsl:variable name="syddata" select="XSLTHelper:GenerateData($productids)"/>

    <xsl:element name="{name($syddata/*)}">
      <!-- copy attributes -->
      <xsl:copy-of select="$syddata/*/@*" />
      <!-- copy data in the right order -->
      <xsl:for-each select="$items//value">
        <xsl:variable name="curValue" select="." />
        <xsl:for-each select="$syddata"><!-- switch focus for the key function -->
          <xsl:copy-of select="key('dataByNummer', normalize-space($curValue))" />
        </xsl:for-each>
      </xsl:for-each>
    </xsl:element>
</xsl:template>

The inner for-each is only one iteration, but the point is to switch the "current document" to $syddata so the key function looks up data elements in that rather than in the $items.

2
votes

You could sort in XSLT 2.0:

<xsl:stylesheet
  version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxml="urn:schemas-microsoft-com:xslt"
  xmlns:XSLTHelper="urn:XSLTHelper"
   xmlns:exslt="http://exslt.org/common"
  xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" 
  exclude-result-prefixes=" msxml ">
  <xsl:output method="html" omit-xml-declaration="yes"/>
  <xsl:param name="currentPage"/>
  <xsl:template match="/">
        <xsl:variable name="items" select="umbraco.library:Split($textWithPipes, '|')"/>
        <xsl:variable name="syddata" select="XSLTHelper:GenerateData($productids)"/>

        <xsl:variable name="sorted">
          <xsl:apply-templates select="$syddata" mode="sort">
            <xsl:with-param name="values" select="$items/values/value/normalize-space()"/>
          </xsl:apply-templates>
        </xsl:variable>
        <xsl:copy-of select="$sorted"/>
  </xsl:template>

  <xsl:template match="syddata" mode="sort">
    <xsl:param name="values"/>
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:perform-sort select="data">
        <xsl:sort select="index-of($values, @Varenummer)"/>
      </xsl:perform-sort>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>