简体   繁体   中英

Grouping elements in XSLT2.0

For the follwoing XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bp_list xmlns="http://example.com/2012/03/01/canonical/somePartner">
<bp>
    <bp_id>1</bp_id>
    <bp_name>FirstName</bp_name>
    <last_changed_date>2016-12-06T18:27:20</last_changed_date>
    <department>
        <department_id>13</department_id>
        <department_name>SomeDepartment</department_name>
    </department>
    <location>
        <location_id>292300</location_id>
        <location_name>Country1</location_name>
        <is_location_owner>false</is_location_owner>
        <address>
            <id>333070831</id>
            <line1> </line1>
            <city>City1</city>
            <country_code>SC</country_code>
            <country_name>Country1</country_name>
            <subdivision_code>          </subdivision_code>
            <validation_status>107</validation_status>
        </address>
        <location_type>
            <location_type_id>510021</location_type_id>
            <location_type_name>store</location_type_name>
        </location_type>
        <location_capability>
            <location_capability_id>13</location_capability_id>
            <location_capability_name>SCton</location_capability_name>
            <location_capability_category>1</location_capability_category>
        </location_capability>
    </location>
    </bp>
<bp>
    <bp_id>3442</bp_id>
    <bp_name>SecondName</bp_name>
    <last_changed_date>2016-12-06T18:27:18</last_changed_date>
     <department>
        <department_id>1</department_id>
        <department_name>AnotherDepartment</department_name>
    </department>
    <location>
        <location_id>292300</location_id>
        <location_name>Country1</location_name>
        <address>
            <id>333070831</id>
            <line1> </line1>
            <city>City1</city>
            <country_code>SC</country_code>
            <country_name>Country1</country_name>
            <subdivision_code>          </subdivision_code>
            <validation_status>107</validation_status>
        </address>
        <location_type>
            <location_type_id>510021</location_type_id>
            <location_type_name>store</location_type_name>
        </location_type>
        <location_capability>
            <location_capability_id>13</location_capability_id>
            <location_capability_name>SCTon</location_capability_name>
            <location_capability_category>1</location_capability_category>
        </location_capability>
        </bp>

2 different bp_ids (1 and 3442) have same location_id (292300).

I want the output like below in a csv :

bp_id,Location_id,location_name,location_type_name
1;3442,292300,Country1,store

As I understand, I basically want to group on bp_ids. This is what I tried:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:ns="http://target.com/2012/03/01/canonical/BusinessPartner">
<xsl:strip-space elements="*"/>
<xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
    <xsl:for-each select="ns:bp_list/ns:bp/ns:location">
        <xsl:choose>
            <xsl:when
                test="ns:bp_location/ns:bp_location_capability/ns:is_primary_capability">
                <xsl:if
                    test="ns:bp_location/ns:bp_location_capability/ns:is_primary_capability/text() != 'true'"><xsl:for-each-group select="ancestor::ns:bp" group-by="ns:bp_id"><xsl:value-of select="ns:bp_id"/></xsl:for-each-group>|<xsl:value-of select="(ns:location_id)"/>|<xsl:value-of
                        select="(ns:location_name)"/>|<xsl:for-each
                            select="ns:location_type"><xsl:value-of
                                select="(ns:location_type_name)"/><xsl:if
                                    test="position() != last()"
                                    ><xsl:text>;</xsl:text></xsl:if></xsl:for-each>|<xsl:for-each select="(ns:bp_location/ns:bp_location_capability)"><xsl:value-of
                                        select="(ns:location_function_capability_name)"
                                    /><xsl:if
                                        test="position() != last()"
                                        ><xsl:text>;</xsl:text></xsl:if></xsl:for-each>|<xsl:value-of select="(ns:address/ns:city)"
                                        />|<xsl:value-of select="(ns:address/ns:subdivision_name)"
                                        />|<xsl:value-of select="(ns:address/ns:country_name)"
                                        />|<xsl:value-of select="(ns:location_status/ns:name)"
                                        /><xsl:text>&#10;</xsl:text>
                </xsl:if>
            </xsl:when>
            <xsl:otherwise> 
                <xsl:for-each-group select="ancestor::ns:bp" group-by="ns:bp_id"><xsl:value-of select="ns:bp_id"/></xsl:for-each-group>|<xsl:value-of select="(ns:location_id)"/>|<xsl:value-of
                    select="(ns:location_name)"/>|<xsl:for-each
                        select="ns:location_type"><xsl:value-of
                            select="(ns:location_type_name)"/><xsl:if
                                test="position() != last()"
                                ><xsl:text>;</xsl:text></xsl:if></xsl:for-each>|<xsl:for-each select="(ns:bp_location/ns:bp_location_capability)"><xsl:value-of
                                    select="(ns:location_function_capability_name)"
                                /><xsl:if
                                    test="position() != last()"
                                    ><xsl:text>;</xsl:text></xsl:if></xsl:for-each>|<xsl:value-of select="(ns:address/ns:city)"
                                    />|<xsl:value-of select="(ns:address/ns:subdivision_name)"
                                    />|<xsl:value-of select="(ns:address/ns:country_name)"
                                    />|<xsl:value-of select="(ns:location_status/ns:name)"
                                    /><xsl:text>&#10;</xsl:text>
            </xsl:otherwise>
        </xsl:choose> </xsl:for-each>
</xsl:template>

I am trying to use for-each-group, but I am not getting the desired result. This is what I get.

bp_id,Location_id,location_name,location_type_name

1,292300,Country1,Store
3442,292300,Country1,Store

I had to use ancestor because the filter condition under choose has to be the first condition and only then rest of the columns have to be obtained.So I need to travel back and forth in the XML sheet. Secondly, please ignore the code for columns that are not mentioned. I am good with the rest of the data. I am stuck only in the first column. I am using XSLT 2.0.

I'm not able to get anything using your XSLT and XML examples. The XSLT is a little tl;dr so I'm not going to try to attempt to debug. I see a ton of | and no commas, so I have a feeling that if it did produce output, it wouldn't be exactly like what you're describing.

EDIT: Now I see that you just have a different namespace uri for the ns namespace prefix in your stylesheet.

As I understand, I basically want to group on bp_ids.

If it were me, I'd group on location_id . I'd create an xsl:key for the bp_id 's so I wouldn't have to use the ancestor:: axis to go back up the tree.

Example...

XML Input (minor fixes to be well-formed)

<bp_list xmlns="http://example.com/2012/03/01/canonical/somePartner">
    <bp>
        <bp_id>1</bp_id>
        <bp_name>FirstName</bp_name>
        <last_changed_date>2016-12-06T18:27:20</last_changed_date>
        <department>
            <department_id>13</department_id>
            <department_name>SomeDepartment</department_name>
        </department>
        <location>
            <location_id>292300</location_id>
            <location_name>Country1</location_name>
            <is_location_owner>false</is_location_owner>
            <address>                
                <id>333070831</id>
                <line1> </line1>
                <city>City1</city>
                <country_code>SC</country_code>
                <country_name>Country1</country_name>
                <subdivision_code>          </subdivision_code>
                <validation_status>107</validation_status>
            </address>
            <location_type>
                <location_type_id>510021</location_type_id>
                <location_type_name>store</location_type_name>
            </location_type>
            <location_capability>
                <location_capability_id>13</location_capability_id>
                <location_capability_name>SCton</location_capability_name>
                <location_capability_category>1</location_capability_category>
            </location_capability>
        </location>
    </bp>
    <bp>
        <bp_id>3442</bp_id>
        <bp_name>SecondName</bp_name>
        <last_changed_date>2016-12-06T18:27:18</last_changed_date>
        <department>
            <department_id>1</department_id>
            <department_name>AnotherDepartment</department_name>
        </department>
        <location>
            <location_id>292300</location_id>
            <location_name>Country1</location_name>
            <address>
                <id>333070831</id>
                <line1> </line1>
                <city>City1</city>
                <country_code>SC</country_code>
                <country_name>Country1</country_name>
                <subdivision_code>          </subdivision_code>
                <validation_status>107</validation_status>
            </address>
            <location_type>
                <location_type_id>510021</location_type_id>
                <location_type_name>store</location_type_name>
            </location_type>
            <location_capability>
                <location_capability_id>13</location_capability_id>
                <location_capability_name>SCTon</location_capability_name>
                <location_capability_category>1</location_capability_category>
            </location_capability>
        </location>
    </bp>
</bp_list>

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xpath-default-namespace="http://example.com/2012/03/01/canonical/somePartner">
  <xsl:output method="text"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="bpid" match="bp" use="location/location_id"/>

  <xsl:template match="/bp_list">
    <xsl:text>bp_id,Location_id,location_name,location_type_name&#xA;</xsl:text>
    <xsl:for-each-group select="bp/location" group-by="location_id">
      <xsl:value-of select="string-join(key('bpid',current-grouping-key())/bp_id,';')"/>
      <xsl:text>,</xsl:text>
      <xsl:for-each select="current-group()[1]">
        <xsl:value-of select="string-join((location_id,location_name,
          location_type/location_type_name),',')"/>
      </xsl:for-each>
      <xsl:text>&#xA;</xsl:text>
    </xsl:for-each-group>
  </xsl:template>

</xsl:stylesheet>

Output

bp_id,Location_id,location_name,location_type_name
1;3442,292300,Country1,store

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM