在XSLT2.0中对元素进行分组

时间:2017-02-28 17:47:42

标签: xml xslt

对于以下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个不同的bp_ids(1和3442)具有相同的location_id(292300)。

我想在csv中输出如下所示:

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

据我了解,我基本上想要分组bp_ids。这就是我试过的:

<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>

我正在尝试使用for-each-group,但我没有得到理想的结果。这就是我得到的。

bp_id,Location_id,location_name,location_type_name

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

我必须使用祖先,因为选择下的过滤条件必须是第一个条件,然后必须获得其余的列。所以我需要在XML表格中来回移动。其次,请忽略未提及的列的代码。我很擅长其他数据。我只被困在第一栏。我正在使用XSLT 2.0。

1 个答案:

答案 0 :(得分:0)

我无法使用您的XSLT和XML示例获取任何内容。 XSLT有点tl; dr所以我不会尝试尝试调试。我看到了大量|而且没有逗号,所以我觉得如果确实产生了输出,那就不会像你所描述的那样。

编辑:现在我看到样式表中的ns名称空间前缀只有一个不同的名称空间uri。

  

据我了解,我基本上想要分组bp_ids。

如果是我,我会分组location_id。我为xsl:key创建了一个bp_id,因此我不必使用ancestor::轴来重新启动树。

示例...

XML输入(次要修复要格式良好)

<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>

<强>输出

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