我正在尝试将XML文档转换为CSV,这是我以前成功完成的事情,但是我的当前XML的结构不同,因为所有子节点元素都被命名为相同(值)。这是XML:
<?xml version="1.0" encoding="utf-8"?>
<dataset xmlns="http://developer.cognos.com/schemas/xmldata/1/" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">
<metadata>
<item name="Employee Number" type="xs:string" length="20"/>
<item name="Last Name" type="xs:string" length="202"/>
<item name="First Name" type="xs:string" length="202"/>
</metadata>
<data>
<row>
<value>000056</value>
<value>Atkinson</value>
<value>Joan</value>
</row>
<row>
<value>000061</value>
<value>Bolton</value>
<value>Larry</value>
</row>
<row>
<value>000092</value>
<value>Hadley</value>
<value>Charles</value>
</row>
</data>
</dataset>
每个节点代表的内容在上面的部分中定义。也就是说,这是我想要的输出:
000056,Atkinson,Joan
000061,Bolton,Larry
000092,Hadley,Charles
这是我开始使用的XSLT:
<?xml version="1.0" encoding="utf-8"?>
<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" omit-xml-declaration="yes" indent="no"/>
<xsl:strip-space elements="*" />
<xsl:template match="/data">
<xsl:for-each select="row">
<!-- Employee Number -->
<xsl:text>,</xsl:text>
<!-- Last Name -->
<xsl:text>,</xsl:text>
<!-- First Name -->
<xsl:text>,</xsl:text>
<!-- new line -->
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
我还没有弄清楚如何正确编码三个数据元素中每个元素的元素,所以我希望实际上在三行输出中只能看到两个逗号。但是,这就是我实际得到的:
000056AtkinsonJoan000061BoltonLarry000092HadleyCharles
它忽略了for-each循环中的所有内容,只输出整个元素中的所有数据。我还发现,即使我将select =“row”属性更改为select =“zzz”(或任何其他值),我仍然会得到相同的结果。那么,我从哪里走了?
答案 0 :(得分:1)
这是因为你有一个默认命名空间。您看到的结果来自built-in templates。您应该使用前缀声明命名空间,并在XPath中使用该前缀。
示例...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="http://developer.cognos.com/schemas/xmldata/1/">
<xsl:output method="text"/>
<xsl:strip-space elements="*" />
<xsl:template match="x:row">
<xsl:apply-templates/>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="x:value">
<xsl:if test="not(position()=1)">
<xsl:text>,</xsl:text>
</xsl:if>
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
这是由输入XML
中的附加命名空间引起的问题xmlns="http://developer.cognos.com/schemas/xmldata/1/"
您可以将带有前缀的命名空间添加到XSLT,例如如
xmlns:c="http://developer.cognos.com/schemas/xmldata/1/"
然后相应地匹配XML的元素:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:c="http://developer.cognos.com/schemas/xmldata/1/"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" omit-xml-declaration="yes" indent="no"/>
<xsl:strip-space elements="*" />
<xsl:template match="//c:data">
<xsl:for-each select="c:row">
<xsl:for-each select="c:value">
<xsl:value-of select="."/>
<xsl:if test="position() != last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
输出:
000056,Atkinson,Joan
000061,Bolton,Larry
000092,Hadley,Charles
我已为这些值添加了第二个for-each
循环,否则您可以使用<xsl:value-of select="c:value[1]"/>
为第一个值等检索该值。