<?xml version="1.0" encoding="UTF-8"?>
<FirstTag version="1.0" createTime="15:59:59" DATE="20161209">
<SecondTag Name="House01">
<a>
<Furniture FURN_ID="FUR00001" FURN_AMT="2" price="10000"/>
<Furniture FURN_ID="FUR00002" FURN_AMT="1" price="20000"/>
</a>
<b>
<Furniture FURN_ID="FUR00003" FURN_AMT="2" price="30000"/>
<Furniture FURN_ID="FUR00004" FURN_AMT="1" price="40000"/>
</b>
<c>
<Furniture FURN_ID="FUR00005" FURN_AMT="2" price="50000"/>
<Furniture FURN_ID="FUR00006" FURN_AMT="1" price="60000"/>
</c>
<d>
<Furniture FURN_ID="FUR00007" FURN_AMT="1" price="70000"/>
<Furniture FURN_ID="FUR00008" FURN_AMT="1" price="80000"/>
</d>
<e>
<Furniture FURN_ID="FUR00009" FURN_AMT="1" price="90000"/>
<Furniture FURN_ID="FUR00010" FURN_AMT="1" price="100000"/>
</e>
<f>
<Furniture FURN_ID="FUR00011" FURN_AMT="1" price="110000"/>
<Furniture FURN_ID="FUR00012" FURN_AMT="2" price="120000"/>
<Furniture FURN_ID="FUR00013" FURN_AMT="2" price="120000"/>
</f>
</SecondTag>
</FirstTag>
上面是我从Java程序生成的简单xml(带有节点值)。关键是,我想将这个xml数据发送到另一个应用程序,其中已经有来自UI /批处理过程的csv加载功能。我已经听说过XSLT但从未使用它,尝试了一些教程,但在将所有值都放入csv时感到困惑。
这里有什么在csv中应该是什么样的(开始,成功后需要做一些计算):
在这个例子中,在一个房子(HOUSE01)中,我想输出不同房间的所有家具(即房间1,b是房间2,c是房间3等)。
我一直在尝试构建XSLT,下面是XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:variable name="delimiter" select="','" />
<!-- define an array containing the fields we are interested in -->
<xsl:variable name="fieldArray">
<field>Name</field>
<field>a</field>
<field>b</field>
<field>c</field>
<field>d</field>
<field>e</field>
<field>f</field>
</xsl:variable>
<xsl:param name="fields" select="document('')/*/xsl:variable[@name='fieldArray']/*" />
<xsl:template match="/">
<!-- output the header row -->
<xsl:for-each select="$fields">
<xsl:if test="position() != 1">
<xsl:value-of select="$delimiter"/>
</xsl:if>
<xsl:value-of select="." />
</xsl:for-each>
<!-- output newline -->
<xsl:text>
</xsl:text>
<xsl:apply-templates select="/*/*"/>
</xsl:template>
<xsl:template match="a">
<xsl:variable name="currNode" select="." />
<!-- output the data row -->
<!-- loop over the field names and find the value of each one in the xml -->
<xsl:for-each select="$fields">
<xsl:if test="position() != 1">
<xsl:value-of select="$delimiter"/>
</xsl:if>
<xsl:value-of select="$currNode/*[name() = current()]/@FURN_ID" />
<!-- <xsl:value-of select="$currNode/*[name() = current()]" /> -->
</xsl:for-each>
<!-- output newline -->
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
我使用了另一个页面的一些引用,并且可以构建一些简单的XSLT来将XML转换为CSV,但是,我需要一些指导来解决我的主要XML问题。在我可以获得循环内的节点值之后的未来,我想总结每个房间的每个家具的总价格。
预期的最终csv结果:
Name,a,b,c,d,e,f
House01,40000,100000,160000,150000,190000,350000
谢谢。
答案 0 :(得分:2)
此XSLT将提供您指定的输出。请参阅demo。
更新:我错过了输出中的a
值。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:text>Name,a,b,c,d,e,f
</xsl:text>
<xsl:apply-templates select="FirstTag/SecondTag/a/Furniture"/>
</xsl:template>
<xsl:template match="Furniture">
<xsl:variable name="pos" select="position()"/>
<xsl:value-of select="../../@Name"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="@FURN_ID"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="../../b/Furniture[position()=$pos]/@FURN_ID"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="../../c/Furniture[position()=$pos]/@FURN_ID"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="../../d/Furniture[position()=$pos]/@FURN_ID"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="../../e/Furniture[position()=$pos]/@FURN_ID"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="../../f/Furniture[position()=$pos]/@FURN_ID"/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
第二个(最终).csv可以按如下方式生成:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="text" encoding="UTF-8" />
<xsl:template match="/FirstTag">
<!-- first pass -->
<xsl:variable name="values-rtf">
<xsl:for-each select="SecondTag/*">
<xsl:copy>
<xsl:for-each select="Furniture">
<value>
<xsl:value-of select="@FURN_AMT * @price"/>
</value>
</xsl:for-each>
</xsl:copy>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="values" select="exsl:node-set($values-rtf)/*" />
<!-- header -->
<xsl:text>Name,</xsl:text>
<xsl:for-each select="$values">
<xsl:value-of select="name()"/>
<xsl:if test="position()!=last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:text> </xsl:text>
<!-- summary -->
<xsl:value-of select="SecondTag/@Name"/>
<xsl:text>,</xsl:text>
<xsl:for-each select="$values">
<xsl:value-of select="sum(value)"/>
<xsl:if test="position()!=last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
这假设您仅限于XSLT 1.0;在XSLT 2.0中,这可以一次完成。
请注意,我假设输入XML将包含单个“house”(SecondTag
),其中包含可变数量的“房间”(a
,{{ 1}},b
等)。否则,不清楚.csv的标题应该是什么。
我不确定你是否还需要临时.csv - 而且无论如何,创建它所需的逻辑都不清楚(为什么输出中缺少c
?)。