xsl:for-each不返回任何值

时间:2019-06-02 12:05:05

标签: xml xslt

我正在尝试将包含多个节点(node6 /总计)的XML文件转换为CSV输出文件,但是XSL中的for-each无法在输出中返回任何内容。

XML代码:

<?xml version='1.0' encoding='utf-8'?>
<File xmlns='urn:uk.co.visitors.v1'>
<Reference>175008-00123</Reference>
<Description>XTR22_2019-01-21</Description>
<Created>2019-01-21T13:45:46</Created>
<node1>
    <node2>
        <ref>REFERENCE</ref>
        <num>12345</num>
        <node3>
            <node4>
                <ref1>012345</ref1>
                <name>scarface</name>
                <location>1876 main street</location>
                <date>2019-01-21</date>
                <ref2>012345</ref2>
                <cost>0.00</cost>
                <paid>9.99</paid>
                <node5>
                    <node6>
                        <detail>check-in</detail>
                        <ondate>2019-01-21</ondate>
                        <time>08:00:00</time>
                        <total>40</total>
                        <update>FALSE</update>
                    </node6>
                    <node6>
                        <detail>check-in</detail>
                        <ondate>2019-01-22</ondate>
                        <time>23:00:00</time>
                        <total>10</total>
                        <update>TRUE</update>
                    </node6>
                    <node6>
                        <detail>check-out</detail>
                        <ondate>2019-01-25</ondate>
                        <time>11:00:00</time>
                        <total>5</total>
                        <update>TRUE</update>
                    </node6>
                </node5>
            </node4>
        </node3>
    </node2>
</node1>
</File>

XSL代码:

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

    <xsl:output method="text" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="no" />

    <xsl:variable name="delimiter" select="'&#59;'" />
    <xsl:variable name="newline" select="'&#10;'" />

    <xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <xsl:text>column1;column2;total</xsl:text>
        <xsl:value-of select="$newline" />
        <xsl:text>X45</xsl:text>
        <xsl:value-of select="$delimiter" />
        <xsl:text>NONE</xsl:text>
        <xsl:value-of select="$delimiter" />

        <xsl:for-each select="/File/node1/node2/node3/node4/node5/node6/total">
            <xsl:value-of select="total" />
            <xsl:value-of select="$delimiter" />
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

我试图更新for-each select的值以将各种路径匹配到所需的节点,但无济于事。

预期结果是一个包含3个标题和3行数据的CSV文件:

column1;column2;total;
X45;NONE;40;
X45;NONE;10;
X45;NONE;5;

当前输出如下:

column1;column2;total;
X45;NONE;

我正在使用的文件大得多,但这是基于上述代码的示例。

在实现此目标方面将提供任何帮助或建议。

1 个答案:

答案 0 :(得分:0)

如前所述,元素位于名称空间中。一种方法是在所有XPath表达式上使用名称空间前缀ns1。然后,您的for-each XPath将如下所示:

/ns1:File/ns1:node1/ns1:node2/ns1:node3/ns1:node4/ns1:node5/ns1:node6

您还必须在ns1:total上使用它。

另一种方法是设置xpath-default-namespace="urn:uk.co.visitors.v1"元素的xsl:stylesheet属性。然后,您可以按原样保留您的代码(就像下面的代码一样)。

另外两件事:除了从total表达式中删除for-each之外,还必须将X45NONE文本移到for-each循环中。

结合所有这些,您的模板可以简化为:

<xsl:template match="/">
    <xsl:text>column1;column2;total</xsl:text>
    <xsl:value-of select="$newline" />
    <xsl:for-each select="/File/node1/node2/node3/node4/node5/node6">
        <xsl:text>X45</xsl:text>
        <xsl:value-of select="$delimiter" />
        <xsl:text>NONE</xsl:text>
        <xsl:value-of select="$delimiter" />
        <xsl:value-of select="total" />
        <xsl:value-of select="concat($delimiter,$newline)" />
    </xsl:for-each>
</xsl:template>

这将为您提供所需的输出。可以进一步简化为

<xsl:template match="/">
    <xsl:text>column1;column2;total</xsl:text>
    <xsl:value-of select="$newline" />
    <xsl:for-each select="/File/node1/node2/node3/node4/node5/node6">
        <xsl:value-of select="concat('X45',$delimiter,'NONE',$delimiter,total,$delimiter,$newline)" />
    </xsl:for-each>
</xsl:template>

给出相同的结果。