XSLT 1.0 Mutliple使用嵌套值进行分组

时间:2016-01-29 11:43:42

标签: xml xslt

我正在尝试将XML转换为另一个XML文件,但是我没有成功选择要包含在每个组中的值。

我尝试了Muenchian方法,但这会丢弃我想要保留的下一级别分组的值。

输入XML

<?xml version="1.0" encoding="utf-8"?>
<NewDataSet>
    <GUID>
        <PolicyNumber>P0001</PolicyNumber>
        <CoverElement>Buildings</CoverElement>
        <LocationID>1</LocationID>
    </GUID>
    <GUID>
        <PolicyNumber>P0002</PolicyNumber>
        <CoverElement>Buildings</CoverElement>
        <LocationID>1</LocationID>
        </GUID>
    <GUID>
        <PolicyNumber>P0002</PolicyNumber>
        <CoverElement>Contents</CoverElement>
        <LocationID>1</LocationID>
    </GUID>
    <GUID>
        <PolicyNumber>P0002</PolicyNumber>
        <CoverElement>Contents</CoverElement>
        <LocationID>2</LocationID>
    </GUID>
    <GUID>
        <PolicyNumber>P0002</PolicyNumber>
        <CoverElement>Liability</CoverElement>
        <LocationID>1</LocationID>
    </GUID>
    <GUID>
        <PolicyNumber>P0002</PolicyNumber>
        <CoverElement>Liability</CoverElement>
        <LocationID>2</LocationID>
    </GUID>
</NewDataSet>

我的XSLT尝试

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <xsl:output method="xml" indent="yes" />

    <xsl:key name="TestKey" match="NewDataSet/GUID/PolicyNumber" use="." />

    <xsl:template match="/">
        <xsl:for-each select="NewDataSet">
            <InputXML>
                <xsl:for-each select="GUID/PolicyNumber[generate-id() = generate-id(key('TestKey', .)[1])]">
                    <PolicyData>
                        <xsl:variable name="currentGroup" select="."/>
                            <PolicyNumber><xsl:value-of select="$currentGroup" /></PolicyNumber>
                                <xsl:for-each select="key('TestKey', $currentGroup)">
                                    <LocationData>
                                        <LocationID><xsl:value-of select="../LocationID"/></LocationID>
                                            <CoverData>
                                                <CoverElement><xsl:value-of select="../CoverElement"/></CoverElement>
                                            </CoverData>
                                    </LocationData> 
                                 </xsl:for-each>
                    </PolicyData>
                </xsl:for-each>
            </InputXML>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

结果

    <?xml version="1.0" encoding="UTF-8"?>
<InputXML>
   <PolicyData>
      <PolicyNumber>P0001</PolicyNumber>
      <LocationData>
         <LocationID>1</LocationID>
         <CoverData>
            <CoverElement>Buildings</CoverElement>
         </CoverData>
      </LocationData>
   </PolicyData>
   <PolicyData>
      <PolicyNumber>P0002</PolicyNumber>
      <LocationData>
         <LocationID>1</LocationID>
         <CoverData>
            <CoverElement>Buildings</CoverElement>
         </CoverData>
      </LocationData>
      <LocationData>
         <LocationID>1</LocationID>
         <CoverData>
            <CoverElement>Contents</CoverElement>
         </CoverData>
      </LocationData>
      <LocationData>
         <LocationID>2</LocationID>
         <CoverData>
            <CoverElement>Contents</CoverElement>
         </CoverData>
      </LocationData>
      <LocationData>
         <LocationID>1</LocationID>
         <CoverData>
            <CoverElement>Liability</CoverElement>
         </CoverData>
      </LocationData>
      <LocationData>
         <LocationID>2</LocationID>
         <CoverData>
            <CoverElement>Liability</CoverElement>
         </CoverData>
      </LocationData>
   </PolicyData>
</InputXML>

试图实现

    <?xml version="1.0" encoding="UTF-8"?>
<InputXML>
   <PolicyData>
      <PolicyNumber>P0001</PolicyNumber>
      <LocationData>
         <LocationID>1</LocationID>
         <CoverData>
            <CoverElement>Buildings</CoverElement>
         </CoverData>
      </LocationData>
   </PolicyData>
   <PolicyData>
      <PolicyNumber>P0002</PolicyNumber>
      <LocationData>
         <LocationID>1</LocationID>
         <CoverData>
            <CoverElement>Buildings</CoverElement>
         </CoverData>
         <CoverData>
            <CoverElement>Contents</CoverElement>
         </CoverData>
         <CoverData>
            <CoverElement>Liability</CoverElement>
         </CoverData>            
      </LocationData>
      <LocationData>
         <LocationID>2</LocationID>
         <CoverData>
            <CoverElement>Contents</CoverElement>
         </CoverData>
         <CoverData>
            <CoverElement>Liability</CoverElement>
         </CoverData>
      </LocationData>
   </PolicyData>
</InputXML>

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:0)

您需要定义三个键,其中下一个级别的键包含上一级键的值:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:output indent="yes"/>

    <xsl:key name="pn" match="GUID" use="PolicyNumber"/>
    <xsl:key name="loc" match="GUID" use="concat(PolicyNumber, '|', LocationID)"/>
    <xsl:key name="cov" match="GUID" use="concat(PolicyNumber, '|', LocationID, '|', CoverElement)"/>

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

    <xsl:template match="NewDataSet">
        <InputXML>
            <xsl:apply-templates select="GUID[generate-id() = generate-id(key('pn', PolicyNumber)[1])]"/>
        </InputXML>
    </xsl:template>

    <xsl:template match="GUID">
        <PolicyData>
            <xsl:copy-of select="PolicyNumber"/>
            <xsl:apply-templates select="key('pn', PolicyNumber)[generate-id() = generate-id(key('loc', concat(PolicyNumber, '|', LocationID))[1])]" mode="loc">
                <xsl:sort select="LocationID" data-type="number"/>
            </xsl:apply-templates>
        </PolicyData>
    </xsl:template>

    <xsl:template match="GUID" mode="loc">
        <LocationData>
            <xsl:copy-of select="LocationID"/>
            <xsl:apply-templates select="key('loc', concat(PolicyNumber, '|', LocationID))[generate-id() = generate-id(key('cov', concat(PolicyNumber, '|', LocationID, '|', CoverElement))[1])]" mode="cov">
                <xsl:sort select="CoverElement"/>
            </xsl:apply-templates>
        </LocationData>
    </xsl:template>

    <xsl:template match="GUID" mode="cov">
        <CoverData>
            <xsl:copy-of select="CoverElement"/>
        </CoverData>
    </xsl:template>

</xsl:transform>

http://xsltransform.net/bnnZWy在线。