Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

xslt nested for each

I have the following xml

    <?xml version="1.0" encoding="UTF-8"?>
<root>
    <employee>
        <name>a</name>
        <company>1</company>
    </employee>
    <employee>
        <name>b</name>
        <company>2</company>
    </employee>
    <employee>
        <name>c</name>
        <company>1</company>
    </employee>
    <employee>
        <name>d</name>
        <campany>2</campany>
    </employee>
    <employee>
        <name>e</name>
        <company>2</company>
    </employee>
    <employee>
        <name>f</name>
        <company>1</company>
    </employee>    
</root>

I would like to have sth like

<root>
 <company>
  <id>1</id>
  <employee>a</employee>
  <employee>c</employee>
  <employee>f</employee>
 </company>
 <company>
  <id>2</id>
  <employee>b</employee>
  <employee>d</employee>
  <employee>e</employee>
 </company>
<root>

I tried using loops

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mdti="urn:com.workday/multiDocumentTransform/Input" xmlns:bc="urn:com.workday/bc"
    exclude-result-prefixes="xs" version="2.0">

    <xsl:output indent="yes"/>
    <xsl:template match="/">

        <root>

            <xsl:variable name="companies" select="distinct-values(root/employee/company)"/>

            <xsl:for-each select="$companies">

                <company>
                    <companyID> <xsl:value-of select="."/></companyID>
                    <employees>
                        <xsl:for-each select="root/employee[company=.]">
                            <employee><xsl:value-of select="."/></employee>
                        </xsl:for-each>
                    </employees>
                </company>
            </xsl:for-each>


        </root>
    </xsl:template>

</xsl:stylesheet>

But it gives me the following error in the second for each:

The required item type of the context item for the child axis is node(), but the supplied expression {.} has item type xs:anyAtomicType

Is it possible to use nested loops here? I know I can get what I want with grouping.

Thanks

Przemek

>Solution :

I know I can get what I want with grouping.

Not sure why you would not want to do exactly that. To do it with distinct-values() instead, you’d need something like:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/root">
    <xsl:variable name="root" select="." />
    <root>
        <xsl:for-each select="distinct-values(employee/company)">
            <company>
                <companyID>
                    <xsl:value-of select="."/>
                </companyID>
                <employees>
                    <xsl:for-each select="$root/employee[company=current()]">
                        <employee>
                            <xsl:value-of select="name"/>
                        </employee>
                    </xsl:for-each>
                </employees>
            </company>
        </xsl:for-each>
    </root>
</xsl:template>

</xsl:stylesheet>

This is because distinct-values() creates a sequence that is separate from the input XML.

Note also that using a predicate to select the employees of each company is inefficient. Using a key would be much better.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading