每次出现的XSL计数

时间:2014-11-05 18:00:14

标签: xml xslt

我想基于几件事增加元素中的值。首先,我想检查元素值的出现,然后在节点中出现相同ID的任何地方更改另一个元素值。

这是xml文件的外观示例:

<?xml version="1.0" encoding="UTF-8" ?>
<XMLLines>
    <XMLLine>
        <ID>"100"</ID>
        <Type>"STEEL"</Type>
        <Value>"1"</Value>
        <ARG1>""</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"100"</ID>
        <Type>"STEEL"</Type>
        <Value>"1"</Value>
        <ARG1>""</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"103"</ID>
        <Type>"STEEL"</Type>
        <Value>"1"</Value>
        <ARG1>""</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"103"</ID>
        <Type>"STEEL"</Type>
        <Value>"1"</Value>
        <ARG1>""</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"143"</ID>
        <Type>"IRON"</Type>
        <Value>"1"</Value>
        <ARG1>""</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"143"</ID>
        <Type>"IRON"</Type>
        <Value>"1"</Value>
        <ARG1>""</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"187"</ID>
        <Type>"STEEL"</Type>
        <Value>"1"</Value>
        <ARG1>""</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"187"</ID>
        <Type>"STEEL"</Type>
        <Value>"1"</Value>
        <ARG1>""</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
</XMLLines>

这是xsl文件:

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

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

    <xsl:key name="TEST1" match="XMLLine[contains(./Type,'STEEL') and (./Value = document('Values.xml')/Values/Value)]" use="ID"/>

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

    <xsl:template match="ARG1[key('TEST1', ../ID)]">
        <xsl:copy>
            <xsl:value-of select="concat('STATUS = ', count(../preceding-sibling::XMLLine[key('TEST1', ID)]) + 1)"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

这是包含值的xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<Values>
    <Value>"1"</Value>
    <Value>"2"</Value>
    <Value>"3"</Value>
    <Value>"4"</Value>
    <Value>"5"</Value>
    <Value>"6"</Value>
    <Value>"7"</Value>
    <Value>"8"</Value>
</Values>

现在,输出看起来像:

<?xml version="1.0"?>
<XMLLines>
    <XMLLine>
        <ID>"100"</ID>
        <Type>"STEEL"</Type>
        <Value>"1"</Value>
        <ARG1>STATUS = 1</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"100"</ID>
        <Type>"STEEL"</Type>
        <Value>"1"</Value>
        <ARG1>STATUS = 2</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"103"</ID>
        <Type>"STEEL"</Type>
        <Value>"1"</Value>
        <ARG1>STATUS = 3</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"103"</ID>
        <Type>"STEEL"</Type>
        <Value>"1"</Value>
        <ARG1>STATUS = 4</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"143"</ID>
        <Type>"IRON"</Type>
        <Value>"1"</Value>
        <ARG1>""</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"143"</ID>
        <Type>"IRON"</Type>
        <Value>"1"</Value>
        <ARG1>""</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"187"</ID>
        <Type>"STEEL"</Type>
        <Value>"1"</Value>
        <ARG1>STATUS = 5</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"187"</ID>
        <Type>"STEEL"</Type>
        <Value>"1"</Value>
        <ARG1>STATUS = 6</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
</XMLLines>

但实际上我需要它每次只增加一次,而不是像上面的输出那样每次增加。所以基本上我想得到以下输出:

<?xml version="1.0"?>
<XMLLines>
    <XMLLine>
        <ID>"100"</ID>
        <Type>"STEEL"</Type>
        <Value>"1"</Value>
        <ARG1>STATUS = 1</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"100"</ID>
        <Type>"STEEL"</Type>
        <Value>"1"</Value>
        <ARG1>STATUS = 1</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"103"</ID>
        <Type>"STEEL"</Type>
        <Value>"1"</Value>
        <ARG1>STATUS = 2</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"103"</ID>
        <Type>"STEEL"</Type>
        <Value>"1"</Value>
        <ARG1>STATUS = 2</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"143"</ID>
        <Type>"IRON"</Type>
        <Value>"1"</Value>
        <ARG1>""</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"143"</ID>
        <Type>"IRON"</Type>
        <Value>"1"</Value>
        <ARG1>""</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"187"</ID>
        <Type>"STEEL"</Type>
        <Value>"1"</Value>
        <ARG1>STATUS = 3</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
    <XMLLine>
        <ID>"187"</ID>
        <Type>"STEEL"</Type>
        <Value>"1"</Value>
        <ARG1>STATUS = 3</ARG1>
        <ARG2>""</ARG2>
        <ARG3>""</ARG3>
    </XMLLine>
</XMLLines>

有关如何使用XSLT 1.0实现此目的的任何想法?谢谢!

2 个答案:

答案 0 :(得分:1)

这是你可以看到的一种方式:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="k" match="XMLLine" use="concat(ID, '|', type)"/>

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

<xsl:template match="ARG1[contains(../Type,'STEEL')]">
    <xsl:copy>
        <xsl:text>STATUS=</xsl:text>
        <xsl:value-of select="count((..|../preceding-sibling::XMLLine)[contains(Type,'STEEL')][count(. | key('k', concat(ID, '|', type))[1]) = 1])" />
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

应用于以下测试输入

<XMLLines>
    <XMLLine>
        <ID>"100"</ID>
        <Type>"STEEL"</Type>
        <ARG1>""</ARG1>
    </XMLLine>
    <XMLLine>
        <ID>"100"</ID>
        <Type>"STEEL"</Type>
        <ARG1>""</ARG1>
    </XMLLine>
    <XMLLine>
        <ID>"100"</ID>
        <Type>"STEEL"</Type>
        <ARG1>""</ARG1>
    </XMLLine>
    <XMLLine>
        <ID>"103"</ID>
        <Type>"STEEL"</Type>
        <ARG1>""</ARG1>
    </XMLLine>
    <XMLLine>
        <ID>"103"</ID>
        <Type>"STEEL"</Type>
        <ARG1>""</ARG1>
    </XMLLine>
    <XMLLine>
        <ID>"143"</ID>
        <Type>"IRON"</Type>
        <ARG1>""</ARG1>
    </XMLLine>
    <XMLLine>
        <ID>"143"</ID>
        <Type>"IRON"</Type>
        <ARG1>""</ARG1>
    </XMLLine>
    <XMLLine>
        <ID>"187"</ID>
        <Type>"STEEL"</Type>
        <ARG1>""</ARG1>
    </XMLLine>
    <XMLLine>
        <ID>"187"</ID>
        <Type>"STEEL"</Type>
        <ARG1>""</ARG1>
    </XMLLine>
</XMLLines>

结果是:

<?xml version="1.0" encoding="UTF-8"?>
<XMLLines>
   <XMLLine>
      <ID>"100"</ID>
      <Type>"STEEL"</Type>
      <ARG1>STATUS=1</ARG1>
   </XMLLine>
   <XMLLine>
      <ID>"100"</ID>
      <Type>"STEEL"</Type>
      <ARG1>STATUS=1</ARG1>
   </XMLLine>
   <XMLLine>
      <ID>"100"</ID>
      <Type>"STEEL"</Type>
      <ARG1>STATUS=1</ARG1>
   </XMLLine>
   <XMLLine>
      <ID>"103"</ID>
      <Type>"STEEL"</Type>
      <ARG1>STATUS=2</ARG1>
   </XMLLine>
   <XMLLine>
      <ID>"103"</ID>
      <Type>"STEEL"</Type>
      <ARG1>STATUS=2</ARG1>
   </XMLLine>
   <XMLLine>
      <ID>"143"</ID>
      <Type>"IRON"</Type>
      <ARG1>""</ARG1>
   </XMLLine>
   <XMLLine>
      <ID>"143"</ID>
      <Type>"IRON"</Type>
      <ARG1>""</ARG1>
   </XMLLine>
   <XMLLine>
      <ID>"187"</ID>
      <Type>"STEEL"</Type>
      <ARG1>STATUS=3</ARG1>
   </XMLLine>
   <XMLLine>
      <ID>"187"</ID>
      <Type>"STEEL"</Type>
      <ARG1>STATUS=3</ARG1>
   </XMLLine>
</XMLLines>

我不确定为什么需要一份列出一些递增数字的单独文件。


虽然上述内容已经比您的尝试更简单,但通过为每个组分配唯一ID,而不是增加数量(这需要计算以前的组),可以使其更简单。例如:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="k" match="XMLLine" use="concat(ID, '|', type)"/>

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

<xsl:template match="ARG1[contains(../Type,'STEEL')]">
    <xsl:copy>
        <xsl:text>STATUS=</xsl:text>
        <xsl:value-of select="generate-id(key('k', concat(../ID, '|', ../type))[1])" />
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

会返回类似的内容:

<?xml version="1.0" encoding="UTF-8"?>
<XMLLines>
   <XMLLine>
      <ID>"100"</ID>
      <Type>"STEEL"</Type>
      <ARG1>STATUS=d0e2</ARG1>
   </XMLLine>
   <XMLLine>
      <ID>"100"</ID>
      <Type>"STEEL"</Type>
      <ARG1>STATUS=d0e2</ARG1>
   </XMLLine>
   <XMLLine>
      <ID>"100"</ID>
      <Type>"STEEL"</Type>
      <ARG1>STATUS=d0e2</ARG1>
   </XMLLine>
   <XMLLine>
      <ID>"103"</ID>
      <Type>"STEEL"</Type>
      <ARG1>STATUS=d0e23</ARG1>
   </XMLLine>
   <XMLLine>
      <ID>"103"</ID>
      <Type>"STEEL"</Type>
      <ARG1>STATUS=d0e23</ARG1>
   </XMLLine>
   <XMLLine>
      <ID>"143"</ID>
      <Type>"IRON"</Type>
      <ARG1>""</ARG1>
   </XMLLine>
   <XMLLine>
      <ID>"143"</ID>
      <Type>"IRON"</Type>
      <ARG1>""</ARG1>
   </XMLLine>
   <XMLLine>
      <ID>"187"</ID>
      <Type>"STEEL"</Type>
      <ARG1>STATUS=d0e51</ARG1>
   </XMLLine>
   <XMLLine>
      <ID>"187"</ID>
      <Type>"STEEL"</Type>
      <ARG1>STATUS=d0e51</ARG1>
   </XMLLine>
</XMLLines>

答案 1 :(得分:0)

实际上,建议的答案对于获得预期的解决方案并没有多大帮助,但我已经找到了解决方法以实现所需的转换。当然,这仅适用于每个匹配事件总共有两个相同ID的当前情况。

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

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

    <xsl:key name="TEST1" match="XMLLine[contains(./Type,'STEEL') and (./Value = document('Values.xml')/Values/Value)]" use="ID"/>

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

    <xsl:template match="ARG1[key('TEST1', ../ID)]">
        <xsl:copy>
            <xsl:value-of select="concat('STATUS = ', round((count(../preceding-sibling::XMLLine[key('TEST1', ID)]) + 1) div 2))"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>