在XSLT中分组问题

时间:2009-12-11 03:47:14

标签: xslt

我需要将以下XML文档分组显示:

Parent          Item           Qty
----------------------------------
                TopLevelAsy      1
SubAsy          Part15           4
Top Assembly    Part19           2
Top Assembly    Part15           2
Top Assembly    SubAsy           2 

但是我使用XSL得到的是:

Parent          Item           Qty
----------------------------------
                TopLevelAsy      1
SubAsy          Part15           2
SubAsy          Part15           2
Top Assembly    Part19           2
Top Assembly    Part15           2
Top Assembly    SubAsy           2 

她是我的XML:

<DOCUMENT>
  <ProductRevision id="id41" name="Top Assembly" accessRefs="#id30" subType="ItemRevision" masterRef="#id47" revision="A"></ProductRevision>
  <ProductRevision id="id15" name="PartA-15" accessRefs="#id30" subType="ItemRevision" masterRef="#id36" revision="A"></ProductRevision>
  <ProductRevision id="id19" name="PartB-19" accessRefs="#id30" subType="ItemRevision" masterRef="#id46" revision="A"></ProductRevision>
  <ProductRevision id="id48" name="SubAsy" accessRefs="#id30" subType="ItemRevision" masterRef="#id76" revision="A"></ProductRevision>
  <ProductView id="id4" ruleRefs="#id2" rootRefs="id7" primaryOccurrenceRef="id7">
    <Occurrence id="id7" instancedRef="#id41" occurrenceRefs="id15 id11 id17 id16 id18 id21">
      <ApplicationRef application="CAD" label="i9BAAAV4xLJc5D/"></ApplicationRef>
      <data>
        <title>TopLevelAsy</title>
        <year>1985</year>
      </data>
    </Occurrence>
    <Occurrence id="id11" instancedRef="#id19" parentRef="#id7">
      <ApplicationRef application="CAD" label="i9BAAAV4xLJc5D/yBEAAAV4xLJc5D/"></ApplicationRef>
      <data>
        <title>Part19</title>
        <year>1988</year>
      </data>
    </Occurrence>
    <Occurrence id="id15" instancedRef="#id15" parentRef="#id7">
      <ApplicationRef application="CAD" label="i9BAAAV4xLJc5D/sdljfjdkLJc5D/"></ApplicationRef>
      <data>
        <title>Part15</title>
        <year>1988</year>
      </data>
    </Occurrence>
    <Occurrence id="id17" instancedRef="#id19" parentRef="#id7">
      <ApplicationRef application="CAD" label="i9BAAAV4xLJc5D/yBEAAAV4xLJc5D/"></ApplicationRef>
      <data>
        <title>Part19</title>
        <year>1988</year>
      </data>
    </Occurrence>
    <Occurrence id="id16" instancedRef="#id15" parentRef="#id7">
      <ApplicationRef application="CAD" label="i9BAAAV4xLJc5D/sdljfjdkLJc5D/"></ApplicationRef>
      <data>
        <title>Part15</title>
        <year>1988</year>
      </data>
    </Occurrence>
    <!-- sub assembly Second occurrence -->
    <Occurrence id="id21" instancedRef="#id48" parentRef="#id7" occurrenceRefs="id153 id135">
      <ApplicationRef application="CAD" label="i9BAAAV4xLJc5D/wesdjdLJc5D/"></ApplicationRef>
      <data>
        <title>Sub Assembly</title>
        <year>1985</year>
      </data>
    </Occurrence>
    <Occurrence id="id153" instancedRef="#id15" parentRef="#id21">
      <ApplicationRef application="CAD" label="i9BAAAV4xLJc5D/wesdjdLJc5D/jkdsdwV4xLJc5D/"></ApplicationRef>
      <data>
        <title>Part15</title>
        <year>1988</year>
      </data>
    </Occurrence>
    <Occurrence id="id135" instancedRef="#id15" parentRef="#id21">
      <ApplicationRef application="CAD" label="i9BAAAV4xLJc5D/wesdjdLJc5D/jkdsdwV4xLJc5D/"></ApplicationRef>
      <data>
        <title>Part15</title>
        <year>1988</year>
      </data>
    </Occurrence>
    <!-- sub assembly first occurrence -->
    <Occurrence id="id18" instancedRef="#id48" parentRef="#id7" occurrenceRefs="id53 id35">
      <ApplicationRef application="CAD" label="i9BAAAV4xLJc5D/wesdjdLJc5D/"></ApplicationRef>
      <data>
        <title>Sub Assembly</title>
        <year>1985</year>
      </data>
    </Occurrence>
    <Occurrence id="id53" instancedRef="#id15" parentRef="#id18">
      <ApplicationRef application="CAD" label="i9BAAAV4xLJc5D/wesdjdLJc5D/vdsfdwV4xLJc5D/"></ApplicationRef>
      <data>
        <title>Part15</title>
        <year>1988</year>
      </data>
    </Occurrence>
    <Occurrence id="id35" instancedRef="#id15" parentRef="#id18">
      <ApplicationRef application="CAD" label="i9BAAAV4xLJc5D/wesdjdLJc5D/vdsfdwV4xLJc5D/"></ApplicationRef>
      <data>
        <title>Part15</title>
        <year>1988</year>
      </data>
    </Occurrence>
  </ProductView>
</DOCUMENT>

我写的XSLT是

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="no" />
  <!--   <xsl:key name="byref" match="Occurrence" use="@instancedRef"/> -->
  <xsl:key name="byid" match="Occurrence" use="concat(@title,@instancedRef)" />
  <xsl:key name="byRef" match="Occurrence" use="@instancedRef" />
  <xsl:template match="/">
    <table border="1">
      <!-- generate the keys for instance occurance-->
      <!-- generate the keys for parent id -->
      <xsl:for-each select="DOCUMENT/ProductView/Occurrence[generate-id(.)=generate-id(key('byid', concat(@instancedRef,@title))[1])]">
        <xsl:sort select="@parentRef" />
        <xsl:variable name="pRef" select="@parentRef" />
        <xsl:variable name="instRef" select="@instancedRef" />
        <xsl:variable name="pdOccId" select="substring-after($pRef,'#')" />
        <xsl:variable name="pdRevIdTag" select="//DOCUMENT/ProductView/Occurrence[@id=$pdOccId]/@instancedRef" />
        <xsl:variable name="pdRevId" select="substring-after($pdRevIdTag,'#')" />
        <xsl:variable name="parentlabeltag" select="ApplicationRef/@label" />
        <tr>
          <td>
            <xsl:text>Parent: </xsl:text>
            <xsl:value-of select="//DOCUMENT/ProductRevision[@id=$pdRevId]/@name" />
          </td>
          <td align="right">
            <xsl:value-of select="data/title" />
            <xsl:text> </xsl:text>
          </td>
          <td>
            <xsl:value-of select="count(key('byid', concat(@instancedRef,@title)))" />
          </td>
        </tr>
      </xsl:for-each>
    </table>
  </xsl:template>
</xsl:stylesheet>

任何帮助都会很棒。请帮我解决这个问题。谢谢。

2 个答案:

答案 0 :(得分:0)

George,你得到2行子组件,因为有两个元素用于具有不同id(id21和id18)的子组件和四个Part15中的两个,两个属于id21,两个属于id18。

由于您是根据父ID进行分组,因此输出似乎正确。如果要将两个子装配元素分组,则需要在连接键中指定父标题而不是父标识。

我只是调整了你的xslt以查看分组。这就是它们的分组方式。如您所见,第二行和第三行的父参考是不同的

Instance Ref:#id41 Parent Ref: Parent:  TopLevelAsy  1 
Instance Ref:#id15 Parent Ref:#id18 Parent: SubAsy Part15  2 
Instance Ref:#id15 Parent Ref:#id21 Parent: SubAsy Part15  2 
Instance Ref:#id19 Parent Ref:#id7 Parent: Top Assembly Part19  2 
Instance Ref:#id15 Parent Ref:#id7 Parent: Top Assembly Part15  2 
Instance Ref:#id48 Parent Ref:#id7 Parent: Top Assembly Sub Assembly  2 

修改

这不是一个完整的解决方案,但你可能需要在这些方面做点什么:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="no"/>
  <!--   <xsl:key name="byref" match="Occurrence" use="@instancedRef"/> -->
  <xsl:key name="bytitle" match="Occurrence" use="data/title"/>
  <xsl:template match="/">
    <table border="1">
      <xsl:for-each select="DOCUMENT/ProductView/Occurrence[generate-id(.)=generate-id(key('bytitle', data/title)[1])]">
        <xsl:sort select="@id"/>
        <xsl:variable name="title" select="data/title" />
        <br />
        Title:<xsl:value-of select="$title"/>
        <xsl:variable name="driver" select="//DOCUMENT/ProductView/Occurrence[data/title = $title]/@id"/>
        Driver:<xsl:value-of select="$driver/."/>
        <!--<xsl:for-each select ="$driver">
          <xsl:value-of select="."/>
        </xsl:for-each>-->
        <xsl:for-each select="//DOCUMENT/ProductView/Occurrence[substring-after(@parentRef,'#') = $driver/.]">
          Child:<xsl:value-of select="data/title"/>
        </xsl:for-each>
      </xsl:for-each>
    </table>
  </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:0)

乔治,

以下是解决方案:

你需要使用2 xslts。第一个xslt将生成一个易于解析的xml。第二个xslt将使用此xml作为其输入来实现所需的结果。

Xslt1:

您的xml将是此xslt的输入

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>
  <xsl:key name="bytitle" match="Occurrence" use="data/title"/>
  <xsl:template match="/">
    <root>

      <xsl:for-each select="DOCUMENT/ProductView/Occurrence[not(@parentRef)]">
        <xsl:element name="Data">
          <xsl:attribute name="parentTitle" />
          <xsl:attribute name="childTitle">
            <xsl:value-of select="data/title"/>
          </xsl:attribute>
        </xsl:element>
      </xsl:for-each>

      <xsl:for-each select="DOCUMENT/ProductView/Occurrence[generate-id(.)=generate-id(key('bytitle', data/title)[1])]">
        <xsl:sort select="@id"/>

        <xsl:variable name="title" select="data/title" />
        <xsl:variable name="driver" select="//DOCUMENT/ProductView/Occurrence[data/title = $title]/@id"/>

        <xsl:for-each select="//DOCUMENT/ProductView/Occurrence[substring-after(@parentRef,'#') = $driver/.]">

          <xsl:element name="Data">
            <xsl:attribute name="parentTitle">
              <xsl:value-of select="$title"/>
            </xsl:attribute>
            <xsl:attribute name="childTitle">
              <xsl:value-of select="data/title"/>
            </xsl:attribute>
          </xsl:element>

        </xsl:for-each>        
      </xsl:for-each>
    </root>
  </xsl:template>
</xsl:stylesheet>

此xslt的输出:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <Data parentTitle="" childTitle="TopLevelAsy" />
  <Data parentTitle="Sub Assembly" childTitle="Part15" />
  <Data parentTitle="Sub Assembly" childTitle="Part15" />
  <Data parentTitle="Sub Assembly" childTitle="Part15" />
  <Data parentTitle="Sub Assembly" childTitle="Part15" />
  <Data parentTitle="TopLevelAsy" childTitle="Part19" />
  <Data parentTitle="TopLevelAsy" childTitle="Part15" />
  <Data parentTitle="TopLevelAsy" childTitle="Part19" />
  <Data parentTitle="TopLevelAsy" childTitle="Part15" />
  <Data parentTitle="TopLevelAsy" childTitle="Sub Assembly" />
  <Data parentTitle="TopLevelAsy" childTitle="Sub Assembly" />
</root>

Xslt2:

xslt 1的输出应该是此xslt的输入

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes"/>
  <xsl:key name="bytitle" match="Data" use="concat(@parentTitle, @childTitle)"/>
  <xsl:template match="/">
    <table border="1">
      <xsl:for-each select="/root/Data[generate-id(.)=generate-id(key('bytitle', concat(@parentTitle, @childTitle))[1])]">
        <xsl:sort select="@parentTitle"/>
        <xsl:variable name="parentTitle" select="@parentTitle"/>
        <xsl:variable name="childTitle" select="@childTitle"/>
        <tr>
          <td>
            <xsl:value-of select="@parentTitle"/>
          </td>
          <td>
            <xsl:value-of select="@childTitle"/>
          </td>
          <td>
            <xsl:value-of select="count(//root/Data[@parentTitle=$parentTitle and @childTitle = $childTitle])"/>
          </td>
        </tr>
      </xsl:for-each>
    </table>
  </xsl:template>
</xsl:stylesheet>

输出:

 TopLevelAsy 1 
Sub Assembly Part15 4 
TopLevelAsy Part19 2 
TopLevelAsy Part15 2 
TopLevelAsy Sub Assembly 2