使用名称/值对处理元素时计算计数

时间:2018-04-20 21:40:55

标签: xslt

我有这种格式的xml。我希望以下面给出的输出格式生成输出。

我正在尝试计算与每个唯一SerialNum相关联的SkuID的总数。在xml中可以多次出现相同的SerialNum。你能否建议我在这种情况下如何计算?

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
        <Skid>
            <NameValuePairs>
                <NameValue>
                    <ID>SerialNum</ID>
                    <Value>12345678</Value>
                </NameValue>
                <NameValue>
                    <ID>calcTotals</ID>
                    <Value>true</Value>
                </NameValue>            
            </NameValuePairs>
            <Box>
                <SkuID>5729305323</SkuID>
            </Box>
            <Box>
                <SkuID>2334923423</SkuID>
            </Box>
        </Skid>
        <Skid>
            <NameValuePairs>
                <NameValue>
                    <ID>SerialNum</ID>
                    <Value>22334455</Value>
                </NameValue>
                <NameValue>
                    <ID>calcTotals</ID>
                    <Value>true</Value>
                </NameValue>            
            </NameValuePairs>
            <Box>
                <SkuID>42342234234</SkuID>
            </Box>
            <Box>
                <SkuID>3243325352</SkuID>
            </Box>
        </Skid>
        <Skid>
        <NameValuePairs>
            <NameValue>
                <ID>SerialNum</ID>
                <Value>12345678</Value>
            </NameValue>
            <NameValue>
                <ID>calcTotals</ID>
                <Value>true</Value>
            </NameValue>        
        </NameValuePairs>
        <Box>
            <SkuID>75547453333</SkuID>
        </Box>
        <Box>
            <SkuID>235356233266</SkuID>
            </Box>
        </Skid>
    </root>

输出:

     <Skids>
          <Box>
             <TrackingNumber>12345678</TrackingNumber>
             <Total>4</Total>
          </Box>
          <Box>
             <TrackingNumber>22334455</TrackingNumber>
             <Total>2</Total>
          </Box>
       </Skids>

2 个答案:

答案 0 :(得分:1)

XSLT 2.0 与for-each-group

一起使用
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>    

   <xsl:template match="root">
       <Skids>
           <xsl:for-each-group select="Skid" group-by="NameValuePairs/NameValue[ID='SerialNum']/Value">
           <Box>
               <TrackingNumber><xsl:value-of select=".//NameValue[ID='SerialNum']/Value"/></TrackingNumber>
                <Total><xsl:value-of select="count(current-group()//Box)"/></Total>
           </Box>
       </xsl:for-each-group>
       </Skids>
   </xsl:template>

</xsl:stylesheet>

XSLT 1.0 与Muenchian方法

一起使用
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>    

  <xsl:key name="Tracking" match="Skid" use=".//NameValue[ID='SerialNum']/Value"/>

    <xsl:template match="root">
       <Skids>
           <xsl:for-each select="Skid[generate-id() = generate-id(key('Tracking', .//NameValue[ID='SerialNum']/Value))]" >
           <Box>
               <TrackingNumber><xsl:value-of select=".//NameValue[ID='SerialNum']/Value"/></TrackingNumber>
               <Total><xsl:value-of select="count(//Skid[.//NameValue[ID='SerialNum']/Value = current()//NameValue[ID='SerialNum']/Value]//Box)"/></Total>
           </Box>
       </xsl:for-each>
       </Skids>
   </xsl:template>

</xsl:stylesheet>

<强>输出

<Skids>
   <Box>
      <TrackingNumber>12345678</TrackingNumber>
      <Total>4</Total>
   </Box>
   <Box>
      <TrackingNumber>22334455</TrackingNumber>
      <Total>2</Total>
   </Box>
</Skids>

答案 1 :(得分:1)

我的解决方案的第一部分是一个名为ids的临时变量, 并且包含(毫不奇怪)ID元素。

每个元素都包含Value元素的内容,其中包含ID个兄弟元素 SerialNum内容。

此外,此ID元素具有cnt属性 - SkuID的数量 &#34;当前&#34;中的元素Skid

此变量中的ID个元素在 for-each-group 循环中处理, 按内容(ID值)对它们进行分组。

所以整个脚本如下所示:

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

  <xsl:template match="root">
    <Skids>
      <xsl:variable name="ids">
        <xsl:for-each select="//Value[../ID = 'SerialNum']">
          <ID>
            <xsl:attribute name="cnt" select="count(../../../Box/SkuID)"/>
            <xsl:value-of select="."/>
          </ID>
        </xsl:for-each>
      </xsl:variable>
      <xsl:copy-of select="$ids"/>
      <xsl:for-each-group select="$ids/ID" group-by=".">
        <Box>
          <ID><xsl:value-of select="."/></ID>
          <Total><xsl:value-of select="sum(current-group()/@cnt)"/></Total>
        </Box>
      </xsl:for-each-group>
    </Skids>
  </xsl:template>
</xsl:transform>

注意:放置了<xsl:copy-of select="$ids"/>指令 仅示范目的。在最终版本中删除它。