XSLT转换问题:从纯XML到多级XML

时间:2013-06-03 11:51:45

标签: xml xslt bpel

我需要在输入XML下面转换为输出XML。能否为此提供任何想法。

我需要在输入XML下面转换为输出XML。能否为此提供任何想法。

输入XML:

<GenericCollection ParamValue="ParamValue1" xmlns="http://www.example.org">
  <Generic>
    <store>Store1</store>
    <metricName>Metric1</metricName>
    <metricValue>1</metricValue>
  </Generic>
  <Generic>
    <store>Store1</store>
    <metricName>Metric2</metricName>
    <metricValue>1</metricValue>
  </Generic>
  <Generic>
    <store>Store2</store>
    <metricName>Metric1</metricName>
    <metricValue>1</metricValue>
  </Generic>
  <Generic>
    <store>Store2</store>
    <metricName>Metric1</metricName>
    <metricValue>2</metricValue>
  </Generic>
  <Generic>
    <store>Store2</store>
    <metricName>Metric2</metricName>
    <metricValue>1</metricValue>
  </Generic>
  <Generic>
    <store>Store3</store>
    <metricName>Metric1</metricName>
    <metricValue>1</metricValue>
  </Generic>
  <Generic>
    <store>Store3</store>
    <metricName>Metric1</metricName>
    <metricValue>2</metricValue>
  </Generic>
</GenericCollection>

输出:

<?xml version = '1.0' encoding = 'UTF-8'?>
<ns4:EnterpriseDocument>
  <ns4:DataSet>
    <ns4:Dimension ref_name="bu_code" value="Store1">
      <ns4:Metric ref_name="Metric1">
        <ns4:Data value="1"/>
      </ns4:Metric>
      <ns4:Metric ref_name="Metric2">
        <ns4:Data value="1"/>
      </ns4:Metric>
    </ns4:Dimension>
    <ns4:Dimension ref_name="bu_code" value="Store2">
      <ns4:Metric ref_name="Metric1">
        <ns4:Data value="1"/>
        <ns4:Data value="2"/>            
      </ns4:Metric>
      <ns4:Metric ref_name="Metric2">
        <ns4:Data value="1"/>
      </ns4:Metric>
    </ns4:Dimension>
    <ns4:Dimension ref_name="bu_code" value="Store3">
      <ns4:Metric ref_name="Metric1">
        <ns4:Data value="1"/>
        <ns4:Data value="2"/>            
      </ns4:Metric>
    </ns4:Dimension>     
  </ns4:DataSet>
</ns4:EnterpriseDocument>
    Thanks,
    Ramesh

2 个答案:

答案 0 :(得分:0)

如果你能够使用XSLT 2.0,那么你应该在这里使用 xsl:for-each-group ,而不是 xsl:for-each ,因为你正试图在这里对元素进行分组。

首先,您通过商店值按通用元素进行分组,因此您可以这样写。

<xsl:for-each-group select="Generic" group-by="store">

然后在这个内容中输入组的* Dimension * 元素,如下所示:

<Dimension ref_name="bu_code" value="{current-grouping-key()}">

接下来,您希望通过 metricName 值进一步对该组中的元素进行分组

<xsl:for-each-group select="current-group()" group-by="metricName">

请注意此处使用 current-group()。您只是迭代当前“商店”组中的元素,而不是遍历所有泛型元素。

最后,要输出所有数据元素,您可以执行此操作

<xsl:for-each select="current-group()">

尝试以下XSLT

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     xpath-default-namespace="http://www.example.org">

<xsl:output method="xml" indent="yes" />

<xsl:template match="/*">
   <EnterpriseDocument>
   <DataSet>
      <xsl:for-each-group select="Generic" group-by="store">
         <Dimension ref_name="bu_code" value="{current-grouping-key()}">
            <xsl:for-each-group select="current-group()" group-by="metricName">
               <Metric ref_name="{current-grouping-key()}">
                  <xsl:for-each select="current-group()">
                    <Data value="{metricValue}"/>
                  </xsl:for-each>
               </Metric>
            </xsl:for-each-group>
         </Dimension>
      </xsl:for-each-group>
    </DataSet>
   </EnterpriseDocument>
</xsl:template>

</xsl:stylesheet>

在XML示例上运行时,输出以下内容(注意,在我的示例中,我不包括任何名称空间,只是为了清晰起见)

<EnterpriseDocument>
   <DataSet>
      <Dimension ref_name="bu_code" value="Store1">
         <Metric ref_name="Metric1">
            <Data value="1"/>
         </Metric>
         <Metric ref_name="Metric2">
            <Data value="1"/>
         </Metric>
      </Dimension>
      <Dimension ref_name="bu_code" value="Store2">
         <Metric ref_name="Metric1">
            <Data value="1"/>
            <Data value="2"/>
         </Metric>
         <Metric ref_name="Metric2">
            <Data value="1"/>
         </Metric>
      </Dimension>
      <Dimension ref_name="bu_code" value="Store3">
         <Metric ref_name="Metric1">
            <Data value="1"/>
            <Data value="2"/>
         </Metric>
      </Dimension>
   </DataSet>
</EnterpriseDocument>

答案 1 :(得分:0)

这是一个xslt-1.0解决方案。 哪个分组基于xsl:key(Muenchian Method

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:e="http://www.example.org"
                xmlns:ns4="http://www.exampl.ns4.org">

    <xsl:strip-space elements="*" />
    <xsl:output method="xml" indent="yes"/>

    <xsl:key name="kStore" match="e:Generic/e:store"  use="."/>
    <xsl:key name="kStoreMetric" match="e:Generic/e:metricName"  use="concat(../e:store,'|', .)"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="e:GenericCollection">
        <ns4:EnterpriseDocument>
        <xsl:for-each select="//e:Generic/e:store[
             generate-id() = generate-id( key('kStore', . ) [1])
              ]" >
            <ns4:DataSet>
                <ns4:Dimension ref_name="bu_code" value="{.}">
                    <xsl:variable name="s" select="." />
                    <xsl:for-each select="//e:metricName[
                            generate-id() = generate-id( key('kStoreMetric', concat($s,'|', .) ) [1])
                            ]" >
                        <ns4:Metric ref_name="{.}">
                            <xsl:variable name="m" select="."/>
                            <xsl:for-each select="key('kStoreMetric', concat($s,'|', $m) )" >
                                <ns4:Data value="{../e:metricValue}"/>
                            </xsl:for-each>
                        </ns4:Metric>
                    </xsl:for-each>
                </ns4:Dimension>
            </ns4:DataSet>
            </xsl:for-each>
        </ns4:EnterpriseDocument>
    </xsl:template>

</xsl:stylesheet>

将生成以下输出:

<ns4:EnterpriseDocument xmlns:ns4="http://www.exampl.ns4.org" xmlns:e="http://www.example.org">
  <ns4:DataSet>
    <ns4:Dimension ref_name="bu_code" value="Store1">
      <ns4:Metric ref_name="Metric1">
        <ns4:Data value="1"/>
      </ns4:Metric>
      <ns4:Metric ref_name="Metric2">
        <ns4:Data value="1"/>
      </ns4:Metric>
    </ns4:Dimension>
  </ns4:DataSet>
  <ns4:DataSet>
    <ns4:Dimension ref_name="bu_code" value="Store2">
      <ns4:Metric ref_name="Metric1">
        <ns4:Data value="1"/>
        <ns4:Data value="2"/>
      </ns4:Metric>
      <ns4:Metric ref_name="Metric2">
        <ns4:Data value="1"/>
      </ns4:Metric>
    </ns4:Dimension>
  </ns4:DataSet>
  <ns4:DataSet>
    <ns4:Dimension ref_name="bu_code" value="Store3">
      <ns4:Metric ref_name="Metric1">
        <ns4:Data value="1"/>
        <ns4:Data value="2"/>
      </ns4:Metric>
    </ns4:Dimension>
  </ns4:DataSet>
</ns4:EnterpriseDocument>