我正在尝试将包含多个节点(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="';'" />
<xsl:variable name="newline" select="' '" />
<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;
我正在使用的文件大得多,但这是基于上述代码的示例。
在实现此目标方面将提供任何帮助或建议。
答案 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
之外,还必须将X45
和NONE
文本移到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>
给出相同的结果。