根据我之前的问题。
我们更改了XML结构,因此输入现在看起来像这样:
<EXPORT>
<DOCUMENTS>
<DOCUMENT>
<INDEX NAME="NAME" VALUE="folder"/>
<INDEX NAME="LOCATION" VALUE="C:here"/>
</DOCUMENT>
<DOCUMENT>
<INDEX NAME="COLOR" VALUE="blue"/>
<INDEX NAME="LOCATION" VALUE="C:here"/>
<INDEX NAME="DATE" VALUE="01-25-2015"/>
</DOCUMENT>
</DOCUMENTS>
</EXPORT>
对于本例,我希望得到以下CSV输出:
NAME,LOCATION,COLOR,DATE
folder, c:here,,
,C:here,blue,01-25-2015
我痛苦地尝试了很多东西,但我不知道generate-id
是如何工作的。最后我得到了这个完全不能工作的XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:variable name="delimiter" select="','"/>
<xsl:key name="fields" match="/EXPORT/DOCUMENTS/*" use="./@name"/>
<xsl:variable name="Fields"
select="/EXPORT/DOCUMENTS/*[generate-id()=generate-id(key('fields', local-name())[1])]" />
<xsl:template match="/">
<xsl:for-each select="$Fields">
<xsl:value-of select="local-name()" />
<xsl:if test="position() < last()">
<xsl:value-of select="$delimiter" />
</xsl:if>
</xsl:for-each>
<xsl:text> </xsl:text>
<xsl:apply-templates select="*/*" />
</xsl:template>
<xsl:template match="*">
<xsl:variable name="this" select="." />
<xsl:for-each select="$Fields">
<xsl:value-of select="$this/*[local-name() = local-name(current())]" />
<xsl:if test="position() < last()">
<xsl:value-of select="$delimiter" />
</xsl:if>
</xsl:for-each>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
我应该改变什么?你有更好的方法吗?
你的第一个问题是与键
<xsl:key name="fields" match="/EXPORT/DOCUMENTS/*" use="./@name"/>
这只是得到DOCUMENT
元素,当你真正想要INDEX
元素。而且,它区分大小写,所以属性是@NAME
而不是@name
<xsl:key name="fields" match="/EXPORT/DOCUMENTS/DOCUMENT/*" use="@NAME"/>
然而,当您开始使用键时,您经常使用local-name()
,但这会获取元素的名称(在本例中,始终是INDEX
),因此您需要将所有出现的local-name()
替换为获取NAME
属性。
<xsl:variable name="Fields"
select="/EXPORT/DOCUMENTS/DOCUMENT/*[generate-id()=generate-id(key('fields', @NAME)[1])]" />
还要注意,当您输出字段值时,您希望输出VALUE
属性的值,而不是元素本身的实际文本值
<xsl:value-of select="$this/*[@NAME = $name]/@VALUE" />
试试这个XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:variable name="delimiter" select="','"/>
<xsl:key name="fields" match="/EXPORT/DOCUMENTS/DOCUMENT/*" use="./@NAME"/>
<xsl:variable name="Fields"
select="/EXPORT/DOCUMENTS/DOCUMENT/*[generate-id()=generate-id(key('fields', @NAME)[1])]" />
<xsl:template match="/">
<xsl:for-each select="$Fields">
<xsl:value-of select="@NAME" />
<xsl:if test="position() < last()">
<xsl:value-of select="$delimiter" />
</xsl:if>
</xsl:for-each>
<xsl:text> </xsl:text>
<xsl:apply-templates select="*/*/*" />
</xsl:template>
<xsl:template match="*">
<xsl:variable name="this" select="." />
<xsl:for-each select="$Fields">
<xsl:variable name="name" select="@NAME" />
<xsl:value-of select="$this/*[@NAME = $name]/@VALUE" />
<xsl:if test="position() < last()">
<xsl:value-of select="$delimiter" />
</xsl:if>
</xsl:for-each>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>