Hi All

I am referring an xml file(document.xml), through document function. Based on the input xml id value, I am taking the corresponding value from document.xml. The output will have this corresponding value and the position in input, as shown in the actualoutput.xml.
However, would like to generate an output xml like expectedOutput.xml, having the attributes Value. Could anyone please point how to change my xsl file to get the expectedOutput.xml?

Dani AI

Generated

Your stylesheet is already on the right track (you use document() to fetch the mapping), but it currently emits one mapValue/position pair per input id. To produce the grouped structure shown in the expected output you need to group input ids by the mapped string from document.xml, emit one <map Value="..."> per distinct mapped string (use "nomatch" when there is no mapping), and then list the original input positions for that group.

A reliable XSLT 1.0 approach is Muenchian grouping: define an xsl:key over the input id elements where the use expression computes the mapped text via document('document.xml'). Select only one representative id per group with the generate-id() trick, then iterate the key to emit all members and compute each member's original index with count(preceding-sibling::id) + 1. This keeps grouping and position logic in the stylesheet and avoids multiple document lookups per position.

Example (XSLT 1.0) that demonstrates the pattern described above:

<?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"/>

  <!-- key groups input id nodes by the mapped text found in document.xml -->
  <xsl:key name="byMapped" match="/*/id" use="document('document.xml')/doc/id[@value = .]"/>

  <xsl:template match="/">
    <result>
      <xsl:for-each select="/*/id[generate-id() = generate-id(key('byMapped', document('document.xml')/doc/id[@value = .])[1])]">
        <xsl:variable name="mapped" select="document('document.xml')/doc/id[@value = .]"/>
        <map>
          <xsl:attribute name="Value">
            <xsl:choose>
              <xsl:when test="$mapped"><xsl:value-of select="$mapped"/></xsl:when>
              <xsl:otherwise>nomatch</xsl:otherwise>
            </xsl:choose>
          </xsl:attribute>
          <xsl:for-each select="key('byMapped', $mapped)">
            <position><xsl:value-of select="count(preceding-sibling::id) + 1"/></position>
          </xsl:for-each>
        </map>
      </xsl:for-each>
    </result>
  </xsl:template>
</xsl:stylesheet>

Notes: Muenchian grouping preserves the order of the first occurrence of each group in the input; add an xsl:sort on the outer for-each if you need a different order. Use normalize-space() around comparisons if input or document values may contain stray whitespace. If using XSLT 2.0, xsl:for-each-group with group-by is a simpler alternative. This approach should produce the grouped <map Value="..."> elements with the correct position children requested by .

Hi All

I am referring an xml file(document.xml), through document function. Based on the input xml id value, I am taking the corresponding value from document.xml. The output will have this corresponding value and the position in input, as shown in the actualoutput.xml.
However, would like to generate an output xml like expectedOutput.xml, having the attributes Value. Could anyone please point how to change my xsl file to get the expectedOutput.xml?

Hi All,

There is some problem with attachment. below are the files
XslFile.xsl

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/">
        <result>
            <xsl:apply-templates select="/*/id"/>

        </result>
    </xsl:template>

    <xsl:template match="id">
        <xsl:variable name="currencydetails" select="document('document.xml')/doc" />
        <xsl:variable name="id">
            <xsl:value-of select="."/>
        </xsl:variable>
        <mapValue>
            <xsl:variable name="fromDocument" select="$currencydetails/id[@value=$id]" />
            <xsl:value-of select="$fromDocument"></xsl:value-of>
        </mapValue>
        <position>
            <xsl:value-of select="position()"/>
        </position>


    </xsl:template>
</xsl:stylesheet>

document.xml

<doc>
    <id value ="123">abc</id>
    <id value ="456">abc</id>
    <id value ="011">def</id>
    <id value ="rty">ghj</id>
    <id value ="iop">qwd</id>
    <id value ="321">ply</id>
</doc>

input.xml

<Root>
    <id>123</id>
    <id>321</id>
    <id>897</id>
    <id>011</id>
    <id>456</id>
</Root>

actualoutput.xml

<?xml version="1.0" encoding="UTF-8"?>
<result>
    <mapValue>abc</mapValue>
    <position>1</position>
    <mapValue>ply</mapValue>
    <position>2</position>
    <mapValue/>
    <position>3</position>
    <mapValue>def</mapValue>
    <position>4</position>
    <mapValue>abc</mapValue>
    <position>5</position>
</result>

expectedOutput.xml

<?xml version="1.0" encoding="UTF-8"?>
<result>
    <map Value ="abc">
    <position>1</position>
    <position>5</position>
    </map>
    <map Value ="nomatch">
    <position>3</position>
    </map>
    <map Value="def">
    <position>4</position>
    </map>
    <map Value ="ply">
    <position>2</position>
    </map>
</result>
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.