我有一些XML,它以下列形式存储表中的列信息和行数据:
<?xml version="1.0" encoding="utf-8"?>
<table>
<columns>
<column id="1">
<name>Date</name>
<type>Date</type>
</column>
<column id="2">
<name>Name</name>
<type>String</type>
</column>
</columns>
<rows>
<row id="1">
<columns>
<column id="1">
<name>Date</name>
<value>1-Dec-2010</value>
<localDate>1-Dec-2010 00:00:00 GMT</localDate>
</column>
<column id="2">
<name>Name</name>
<value>Jim</value>
</column>
</columns>
</row>
<row id="2">
<columns>
<column id="1">
<name>Date</name>
<value>2-Dec-2010</value>
<localDate>2-Dec-2010 00:00:00 GMT</localDate>
</column>
<column id="2">
<name>Name</name>
<value>Jane</value>
</column>
</columns>
</row>
</rows>
</table>
注意:这是我的xml的缩减版本。我有更多行,并在每列上存储更多信息。
是否可以应用XSL转换,该转换将迭代xml中的每一行并输出每个列值。如果列的类型为DateTime(在列信息中指定),我想输出 localDate 文本值,否则我将只输出值文本值。
我可以做一点XSL,但我不确定如何检查文档的不同部分,它实际上将从tableModel / rows / row / columns /列映射到tableModel / columns /列。
我基本上将其输出为CSV。我有代码来附加每个/ tableModel / rows / row / columns / column xml的列信息,但我认为这是不必要的,它使得xm对于Netbeans / Visual Studio来说太大了(大约7MB)。
我想要的输出是:
Date,Name
1-Dec-2010 00:00:00 GMT,Jim
2-Dec-2010 00:00:00 GMT,Jane
非常感谢,
Andez
答案 0 :(得分:2)
以下内容为您的输入样本
生成所描述的输出<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:param name="sep" select="','"/>
<xsl:param name="lf" select="' '"/>
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:apply-templates select="table/columns/column/name"/>
<xsl:value-of select="$lf"/>
<xsl:apply-templates select="table/rows/row"/>
</xsl:template>
<xsl:template match="column/name">
<xsl:value-of select="."/>
<xsl:if test="position() != last()">
<xsl:value-of select="$sep"/>
</xsl:if>
</xsl:template>
<xsl:template match="rows/row">
<xsl:apply-templates select="columns/column"/>
<xsl:value-of select="$lf"/>
</xsl:template>
<xsl:template match="row/columns/column[not(localDate)]">
<xsl:value-of select="value"/>
<xsl:if test="position() != last()">
<xsl:value-of select="$sep"/>
</xsl:if>
</xsl:template>
<xsl:template match="row/columns/column[localDate]">
<xsl:value-of select="localDate"/>
<xsl:if test="position() != last()">
<xsl:value-of select="$sep"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
但它没有查看相应的列类型,只是输出localDate元素(如果存在)。那够了吗? 还请说明是否可以使用XSLT 2.0(由AltovaXML Tools或Saxon 9实现),这使得这些东西更容易。
[edit]我想在匹配模式中使用一个密钥,虽然在XSLT 1.0中不允许这样做,但它似乎有效,所以以下是您需求的更好实现:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:param name="sep" select="','"/>
<xsl:param name="lf" select="' '"/>
<xsl:key name="k1" match="table/columns/column" use="@id"/>
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:apply-templates select="table/columns/column/name"/>
<xsl:value-of select="$lf"/>
<xsl:apply-templates select="table/rows/row"/>
</xsl:template>
<xsl:template match="column/name">
<xsl:value-of select="."/>
<xsl:if test="position() != last()">
<xsl:value-of select="$sep"/>
</xsl:if>
</xsl:template>
<xsl:template match="rows/row">
<xsl:apply-templates select="columns/column"/>
<xsl:value-of select="$lf"/>
</xsl:template>
<xsl:template match="row/columns/column[not(key('k1', @id)/type = 'Date')]">
<xsl:value-of select="value"/>
<xsl:if test="position() != last()">
<xsl:value-of select="$sep"/>
</xsl:if>
</xsl:template>
<xsl:template match="row/columns/column[key('k1', @id)/type = 'Date']">
<xsl:value-of select="localDate"/>
<xsl:if test="position() != last()">
<xsl:value-of select="$sep"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
这个不那么冗长但可能......深奥的样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="kDataType" match="type" use="../@id"/>
<xsl:template match="value|table/*/*/name">
<xsl:variable name="vIsDateType"
select="key('kDataType',../@id)='Date'"/>
<xsl:value-of
select="concat(substring(',',
1 div boolean(../preceding-sibling::*)),
self::name,
self::value[not($vIsDateType)],
../localDate[$vIsDateType],
substring('
',
1 div not(../following-sibling::*)))"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
输出:
Date,Name
1-Dec-2010 00:00:00 GMT,Jim
2-Dec-2010 00:00:00 GMT,Jane