在下面的xml结构中,如果记录类型是" ADD"
,我需要使用xsl来汇总每种记录类型的成本值。<records>
...irrelevant nodes...
<recordType>NO</recordType>
<recordType>ADD</recordType>
<recordType>ADD</recordType>
... irrelevant nodes...
<LdgCost>1</LdgCost>
<LabCostIn>2</LabCostIn>
<LabCostOut>3</LabCostOut>
<LdgCost>4</LdgCost>
<LabCostIn>5</LabCostIn>
<LabCostOut>6</LabCostOut>
<LdgCost>7</LdgCost>
<LabCostIn>8</LabCostIn>
<LabCostOut>9</LabCostOut>
...irrelevant nodes...
</records>
(记录类型的成本是与记录类型相同的索引中的以下元素)。这意味着第一个位置的recordType类型为&#34; NO&#34;不需要添加其值
<LdgCost>1</LdgCost>
<LabCostIn>2</LabCostIn>
<LabCostOut>3</LabCostOut>
不需要总结。但是,接下来的两种记录类型是&#34; ADD&#34;因此我需要总结
的值<LdgCost>4</LdgCost>
<LabCostIn>5</LabCostIn>
<LabCostOut>6</LabCostOut>
<LdgCost>7</LdgCost>
<LabCostIn>8</LabCostIn>
<LabCostOut>9</LabCostOut>
并将其设为我的总数。输出只是一个总元素
<total>39</total>
逻辑上,如果使用父子节点,上述xml结构所代表的结构如下:
<records>
<record>
<recordType>NO</recordType>
<LdgCost>1</LdgCost>
<LabCostIn>2</LabCostIn>
<LabCostOut>3</LabCostOut>
</record>
<record>
<recordType>ADD</recordType>
<LdgCost>4</LdgCost>
<LabCostIn>5</LabCostIn>
<LabCostOut>6</LabCostOut>
</record>
<record>
<recordType>ADD</recordType>
<LdgCost>7</LdgCost>
<LabCostIn>8</LabCostIn>
<LabCostOut>9</LabCostOut>
</record>
</records>
然而,不是使用这个结构,我必须根据兄弟元素的索引建立父子关系。
我手动执行此操作的方式如下:
找到第一个<recordType>
元素,检查值是否为ADD或NO。由于价值为NO,我跳过这一个。
找到下一个<recordType>
元素,检查值是否为ADD或NO。由于价值是ADD,那么我需要找到与第二条记录相关的3个成本。这些成本要素保证存在,并且位于与其recordType对应的索引中。
查找<LdgCost>
[2]元素值并将其添加到sum。 (索引是两个,因为我们在第二个记录类型上,因为我们跳过第一个记录,并忽略了它的成本)
查找<LdgCostIn>
[2]元素值并将其添加到总和中。
查找<LdgCostOut>
[2]元素值并将其添加到总和中。
现在我们已经将第二条记录中的三个成本添加到总和中,然后我们转到第三个<recordType>
元素并检查其值。由于该值为ADD,我们发现与第三条记录相关的3个成本。
查找<LdgCost>
[3]元素值并将其添加到sum。(索引为3,因为我们在第三个recordType上)
查找<LdgCostIn>
[3]元素值并将其添加到总和中。
查找<LdgCostOut>
[3]元素值并将其添加到总和中。
我们不再需要处理<recordType>
元素,因此我们会返回39的总和。
答案 0 :(得分:2)
如果您知道可以使用的元素名称
<xsl:template match="/records">
<xsl:variable name="positions" select="index-of(recordType, 'ADD')"/>
<total>
<xsl:value-of select="sum(LdgCost[position() = $positions]
| LabCostIn[position() = $positions]
| LabCostOut[position() = $positions])"/>
</total>
</xsl:template>
答案 1 :(得分:1)
---为回应澄清而编辑---
XSLT 2.0
<xsl:stylesheet version="2.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:template match="/records">
<xsl:variable name="i" select="index-of(recordType, 'ADD')" />
<xsl:variable name="costs" select="LabCost | LabCostIn | LabCostOut" />
<total>
<xsl:copy-of select="sum($costs[(position() - 1) idiv 3 + 1 = $i])"/>
</total>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:1)
所需的总和可以表示为单个XPath 2.0表达式。以下是两种不同的表达方式:
sum(/*/*[name()=('LdgCost', 'LabCostIn', 'LabCostOut')]
[for $vPos in ceiling(position() div 3)
return
/*/recordType[$vPos] eq 'ADD']
)
或强>:
sum(for $vAddPositions in index-of(/*/recordType, 'ADD')
return
/*/*[name()=('LdgCost', 'LabCostIn', 'LabCostOut')]
[ceiling(position() div 3) = $vAddPositions]
)
这是一个基于XSLT 2.0的验证(转换只输出评估这两个表达式的结果):
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:sequence select=
"sum(/*/*[name()=('LdgCost', 'LabCostIn', 'LabCostOut')]
[for $vPos in ceiling(position() div 3)
return
/*/recordType[$vPos] eq 'ADD']
)
"/>
=====================
<xsl:sequence select=
"sum(for $vAddPositions in index-of(/*/recordType, 'ADD')
return
/*/*[name()=('LdgCost', 'LabCostIn', 'LabCostOut')]
[ceiling(position() div 3) = $vAddPositions]
)
"/>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<records>
...irrelevant nodes...
<recordType>NO</recordType>
<recordType>ADD</recordType>
<recordType>ADD</recordType>
... irrelevant nodes...
<LdgCost>1</LdgCost>
<LabCostIn>2</LabCostIn>
<LabCostOut>3</LabCostOut>
<LdgCost>4</LdgCost>
<LabCostIn>5</LabCostIn>
<LabCostOut>6</LabCostOut>
<LdgCost>7</LdgCost>
<LabCostIn>8</LabCostIn>
<LabCostOut>9</LabCostOut>
...irrelevant nodes...
</records>
产生了想要的正确结果:
39
=====================
39
答案 3 :(得分:0)
这样做可以满足您的需求:
使用XSLT 1和MSXML
<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:output method="xml"/>
<xsl:template match="/">
<!-- create a set of node for all the values that need to be added -->
<xsl:variable name="values">
<xsl:apply-templates select="records/recordType"/>
</xsl:variable>
<!-- at this point $values contains a fragment with groups of
<LdgCost>value</LdgCost>
<LabCostIn>value</LabCostIn>
<LabCostOut>value</LabCostOut>
-->
<total>
<!-- sum up all the values -->
<xsl:value-of select="sum(msxsl:node-set($values)/*)"/>
</total>
</xsl:template>
<xsl:template match="recordType[.='ADD']">
<!-- the index for the ADD recordType -->
<xsl:variable name="index" select="position()"/>
<!-- select costs using index -->
<xsl:copy-of select="/records/LdgCost[$index]"/>
<xsl:copy-of select="/records/LabCostIn[$index]"/>
<xsl:copy-of select="/records/LabCostOut[$index]"/>
</xsl:template>
</xsl:stylesheet>
我在这里使用的是节点集功能,每个xslt处理器的功能都不同。
使用您的数据,它返回一个节点:
<total>39</total>