XSLT计算一个不同的节点

时间:2017-09-14 16:19:24

标签: xml csv xslt

我需要使用XSLT文件将xml转换为csv。多么容易。

我还需要计算节点中的不同值并将它们插入每一行。这是我不知道该怎么做的地方。

我需要计算的节点可以在下面的示例中看到。它被称为< Id>。

我基本上想要计算所有唯一的id,并将结果插入每个订单行。

因为我的例子有两个&lt; id&gt;值为1且一个<1的节点id&gt;值为4的节点,结果为2。

提前感谢任何帮助。

XML:

<?xml version="1.0" encoding="utf-8"?>
<Picked xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <OrderLines>
        <OrderLine>
            <OrderId>1345
            </OrderId>
            <Missions>
                <Mission>
                    <ContainerIds>
                        <Container>
                            <Id>1
                            </Id>
                        </Container>
                    </ContainerIds>
                </Mission>
            </Missions>
        </OrderLine>
        <OrderLine>
            <OrderId>13456
            </OrderId>
            <Missions>
                <Mission>
                    <ContainerIds>
                        <Container>
                            <Id>1
                            </Id>
                        </Container>
                    </ContainerIds>
                </Mission>
            </Missions>
        </OrderLine>
        <OrderLine>
            <OrderId>134567
            </OrderId>
            <Missions>
                <Mission>
                    <ContainerIds>
                        <Container>
                            <Id>4
                            </Id>
                        </Container>
                    </ContainerIds>
                </Mission>
            </Missions>
        </OrderLine>
    </OrderLines>
</Picked>

期望的结果:

    Orderid;Id
    1345;2
    13456;2
    134567;2
到目前为止

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:output method="text" encoding="UTF-8"/>
    <xsl:template match='/'>

    <xsl:text>Orderid;Id</xsl:text>
    <xsl:text>&#10;</xsl:text>

    <xsl:for-each select="/Picked/OrderLines/OrderLine">
      <xsl:value-of select="OrderId"/>
      <xsl:text>;</xsl:text>
      <xsl:value-of select="Missions/Mission/ContainerIds/Container/Id"/>                           
      <xsl:if test="position()!=last()">
        <xsl:text>&#10;</xsl:text>
      </xsl:if>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

到目前为止我的结果:

    Orderid;Id
    1345;1
    13456;1
    134567;4

2 个答案:

答案 0 :(得分:2)

用于比较的XSLT 3.0解决方案:

<xsl:stylesheet version="3.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    expand-text="yes">

    <xsl:output method="text" encoding="UTF-8"/>

    <xsl:template match='/'>
        <xsl:text>Orderid;Id&#10;</xsl:text>
        <xsl:for-each select="/Picked/OrderLines/OrderLine">
           <xsl:text>{OrderId};{count(distinct-values(//Id))}&#10;</xsl:text>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:1)

XSLT-1.0中有几种可能获得不同的值。它们在this good SO answer中列举。

我使用了Nick Grealy的方法,避免使用generate-id(),并对结果节点进行了计数。

<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="text" encoding="UTF-8"/>

    <xsl:template match='/'>
        <xsl:text>Orderid;Id</xsl:text>
        <xsl:text>&#10;</xsl:text>
        <xsl:for-each select="/Picked/OrderLines/OrderLine">
            <xsl:value-of select="OrderId"/>
            <xsl:text>;</xsl:text>
            <xsl:value-of select="count(//Id[not(.=preceding::*)])"/> <!-- count above all Id's in document -->
            <xsl:if test="position()!=last()">
                <xsl:text>&#10;</xsl:text>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

输出:

Orderid;Id
1345;2
13456;2
134567;2