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 select attributes from another node

This is my XML file :

<root>
    <headers>
        <header value="type1" />
        <header value="type3" />
        <header value="type2" />
    </headers>
    <data type1="data1_1" type2="data1_2" type3="data1_3" />
    <data type1="data2_1" type2="data2_2" type3="data2_3" />
</root>

And I want to generate CSV with only headers listed in headers section. This is my xslt file :

<?xml version="1.0" encoding="UTF-16"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="no" encoding="unicode" />
<xsl:template match="root">
     <xsl:apply-templates/>
</xsl:template>


<xsl:template match="headers">
    <xsl:apply-templates/><xsl:text>&#xa;</xsl:text>
</xsl:template>


<xsl:template name="separator">
    <xsl:text>&#x09;</xsl:text>
</xsl:template>

<!-- display first line header work ok -->
<xsl:template match="header">
    <xsl:value-of select="@value" />
    <xsl:if test="position() != last()">
      <xsl:call-template name="separator" />
   </xsl:if>
</xsl:template>


<xsl:key name="mykey" match="header" use="@value" />

<!-- For each data parameters check if exist in header and display with the good order ! NOT WORK -->
<xsl:template match="data">
    <xsl:for-each select="@*">
        <xsl:if test="key('mykey', name())">
            <xsl:value-of select="." />
            <xsl:if test="position() != last()">
                <xsl:call-template name="separator" />
            </xsl:if>
        </xsl:if>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

I want this output format (CSV):

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

type1 type3 type2
data1_1 data1_3 data1_2
data2_1 data2_3 data2_2

But my output is ( data type2 is not under correct header ):

type1 type3 type2
data1_1 data1_2 data1_3
data2_1 data2_2 data2_3

>Solution :

Attributes have no set order. Elements do. So let’s use the elements to provide your ordering:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="no" encoding="unicode" />
<xsl:template match="Results">
     <xsl:apply-templates/>
</xsl:template>

<xsl:template match="headers">
    <xsl:apply-templates/><xsl:text>&#xa;</xsl:text>
</xsl:template>

<xsl:template name="separator">
    <xsl:text>&#x09;</xsl:text>
</xsl:template>

<!-- display first line header work ok -->
<xsl:template match="header">
    <xsl:value-of select="@value" />
    <xsl:if test="position() != last()">
      <xsl:call-template name="separator" />
   </xsl:if>
</xsl:template>

<!-- Use the order of the headers to choose the order of the attributes. -->
<xsl:template match="data">
    <xsl:variable name="data" select="."/>
    <xsl:for-each select="/root/headers/header">
        <xsl:value-of select="$data/@*[name()=current()/@value]"/>        
            <xsl:if test="position() != last()">
                <xsl:call-template name="separator" />
            </xsl:if>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Output:

    type1   
    type3   
    type2   


data1_1 data1_3 data1_2
data2_1 data2_3 data2_2

The headers are on separate lines because I didn’t change that part of your code.

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