第一个子节点不存在时,使用SUM问题进行XSLT分组

时间:2016-12-14 06:43:46

标签: xslt xslt-1.0 xslt-grouping

XML

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="State.xsl" ?>

<StateData>
<States>    
    <State>
        <StateName>State1</StateName>
        <Districts>
            <District>
                <TranslatedDistrictName>AT</TranslatedDistrictName>
                <DistrictName>A</DistrictName>              
                <Population>10000</Population>              
            </District>         
            <District>
                <TranslatedDistrictName>AT</TranslatedDistrictName>
                <DistrictName>B</DistrictName>      
                <Population>5000</Population>                   
            </District>     
            <District>
                <TranslatedDistrictName>AT</TranslatedDistrictName>
                <DistrictName>A</DistrictName>
                <Population>2000</Population>               
            </District>                 
        </Districts>
    </State>
    <State>
        <StateName>State2</StateName>
        <Districts>
            <District>
                <TranslatedDistrictName>AC</TranslatedDistrictName>
                <DistrictName>C</DistrictName>
                <Population>8000</Population>               
            </District>         
            <District>
                <TranslatedDistrictName>AT</TranslatedDistrictName>
                <DistrictName>B</DistrictName>      
                <Population>5500</Population>                   
            </District>     
            <District>
                <TranslatedDistrictName>AP</TranslatedDistrictName>
                <DistrictName>A</DistrictName>
                <Population>1000</Population>               
            </District> 
        </Districts>
    </State>
</States>
</StateData>

XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">  
   <xsl:key name="district-by-state" match="District" use="concat(TranslatedDistrictName,
                       DistrictName[not(string(../TranslatedDistrictName))])" /> 
    <xsl:template match="StateData">
        <xsl:for-each select="States/State">                

                <xsl:for-each select="Districts/District[count(. | key('district-by-state', concat(TranslatedDistrictName,
                       DistrictName[not(string(../TranslatedDistrictName))]))[1]) = 1]">    
                    <hr/>                   
                    - <xsl:value-of select="concat(TranslatedDistrictName,
                       DistrictName[not(string(../TranslatedDistrictName))])"/> 
                     --<xsl:value-of select="sum(key('district-by-state', concat(TranslatedDistrictName,
                        DistrictName[not(string(../TranslatedDistrictName))]))/Population)" />
                </xsl:for-each>
            <hr/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

结果

  • AT --22500

  • AC --8000

  • AP --1000

截至目前,这是完美的工作但是我添加一个没有地区SUM的新州的那一刻工作不正常。

注意 - 添加了一个没有Districts标记的新州,而是使用&#34; District1&#34;

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="State.xsl" ?>

<StateData>
<States>
    <State>
        <StateName>State3</StateName>
        <Districts1>
            <District>
                <TranslatedDistrictName>AT</TranslatedDistrictName>
                <DistrictName>A</DistrictName>              
                <Population>10000</Population>              
            </District>         
            <District>
                <TranslatedDistrictName>AT</TranslatedDistrictName>
                <DistrictName>B</DistrictName>      
                <Population>5000</Population>                   
            </District>     
            <District>
                <TranslatedDistrictName>AT</TranslatedDistrictName>
                <DistrictName>A</DistrictName>
                <Population>2000</Population>               
            </District>                 
        </Districts1>
    </State>
    <State>
        <StateName>State1</StateName>
        <Districts>
            <District>
                <TranslatedDistrictName>AT</TranslatedDistrictName>
                <DistrictName>A</DistrictName>              
                <Population>10000</Population>              
            </District>         
            <District>
                <TranslatedDistrictName>AT</TranslatedDistrictName>
                <DistrictName>B</DistrictName>      
                <Population>5000</Population>                   
            </District>     
            <District>
                <TranslatedDistrictName>AT</TranslatedDistrictName>
                <DistrictName>A</DistrictName>
                <Population>2000</Population>               
            </District>                 
        </Districts>
    </State>
    <State>
        <StateName>State2</StateName>
        <Districts>
            <District>
                <TranslatedDistrictName>AC</TranslatedDistrictName>
                <DistrictName>C</DistrictName>
                <Population>8000</Population>               
            </District>         
            <District>
                <TranslatedDistrictName>AT</TranslatedDistrictName>
                <DistrictName>B</DistrictName>      
                <Population>5500</Population>                   
            </District>     
            <District>
                <TranslatedDistrictName>AP</TranslatedDistrictName>
                <DistrictName>A</DistrictName>
                <Population>1000</Population>               
            </District> 
        </Districts>
    </State>
</States>
</StateData>

结果

  • AC --8000
  • AP --1000

此处,区域AT的SUM缺失。

预期结果

AT --22500 AC - 8000 AP --1000

1 个答案:

答案 0 :(得分:0)

如果您不想在District元素下选择Districts1个元素,那么一个解决方案就是修改密钥以仅匹配District下的Districts个元素元素

  <xsl:key name="district-by-state" match="Districts/District" use="concat(TranslatedDistrictName,
                   DistrictName[not(string(../TranslatedDistrictName))])" /> 

您可能还想将xsl:for-each更改为仅选择包含子State个节点的Districts元素

<xsl:for-each select="States/State[Districts]">

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">  
   <xsl:key name="district-by-state" match="Districts/District" use="concat(TranslatedDistrictName,
                       DistrictName[not(string(../TranslatedDistrictName))])" /> 

    <xsl:template match="StateData">
        <xsl:for-each select="States/State[Districts]">                

                <xsl:for-each select="Districts/District[count(. | key('district-by-state', concat(TranslatedDistrictName,
                       DistrictName[not(string(../TranslatedDistrictName))]))[1]) = 1]">    
                    <hr/>                   
                    - <xsl:value-of select="concat(TranslatedDistrictName,
                       DistrictName[not(string(../TranslatedDistrictName))])"/> 
                     --<xsl:value-of select="sum(key('district-by-state', concat(TranslatedDistrictName,
                        DistrictName[not(string(../TranslatedDistrictName))]))/Population)" />
                </xsl:for-each>
            <hr/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>