【问题标题】:XML Convertion to CSVXML 转换为 CSV
【发布时间】:2016-12-14 09:43:16
【问题描述】:
<?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="FUR00001" FURN_AMT="2" price="30000"/>
        <Furniture FURN_ID="FUR00003" FURN_AMT="1" price="40000"/>
    </b>
    <c>
        <Furniture FURN_ID="FUR00002" FURN_AMT="2" price="50000"/>
        <Furniture FURN_ID="FUR00003" FURN_AMT="1" price="60000"/>
    </c>
    <d>
        <Furniture FURN_ID="FUR00001" FURN_AMT="1" price="70000"/>
        <Furniture FURN_ID="FUR00002" FURN_AMT="2" price="80000"/>
    </d>
    <e>
        <Furniture FURN_ID="FUR00002" FURN_AMT="1" price="90000"/>
        <Furniture FURN_ID="FUR00003" FURN_AMT="2" price="100000"/>
    </e>
    <f>
        <Furniture FURN_ID="FUR00001" FURN_AMT="1" price="110000"/>
        <Furniture FURN_ID="FUR00002" FURN_AMT="2" price="120000"/>
        <Furniture FURN_ID="FUR00003" FURN_AMT="2" price="120000"/>
    </f>
  </SecondTag>
</FirstTag>

上面是我从 Java 程序生成的简单 xml(带有节点值)。关键是,我想将此 xml 数据发送到另一个应用程序,其中已经有来自 UI/批处理过程的 csv 加载功能。我听说过 XSLT,但从未使用过它,尝试了一些教程,但在将所有值放入 csv 时感到困惑。

这是它在 csv 中的样子(开始,成功后需要做一些计算):

在这个例子中,在一所房子 (HOUSE01) 中,我想输出不同房间的所有家具(即 a 是房间 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:template match="/">
    <xsl:text>Name,Furn_Id,a,b,c,d,e,f
</xsl:text>
  <xsl:variable name="delimiter" select="','" />

    <xsl:for-each select="//SecondTag">
<xsl:variable name="hname" select="@Name"/>

        <xsl:for-each select="f/Furniture">

            <xsl:value-of select='$hname' />
            <xsl:value-of select="$delimiter"/>

            <xsl:variable name="var1" select="@FURN_ID"/>
            <xsl:variable name="varamt1" select="@FURN_AMT"/>

             <xsl:for-each select="//a/Furniture">


                 <xsl:variable name="var2" select="@FURN_ID"/>
                 <xsl:variable name="varamt2" select="@FURN_AMT"/>

                <xsl:if test="$var1 = $var2">

                        <xsl:value-of select='$var2' />
                        <xsl:value-of select="$delimiter"/>
                        <xsl:value-of select='$varamt2' />
                        <xsl:value-of select="$delimiter"/>
                </xsl:if>

            </xsl:for-each>

<xsl:text>
</xsl:text>

        </xsl:for-each>

    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

我正在使用来自另一个页面的一些参考,并且可以构建一些简单的 XSLT 来将 XML 转换为 CSV,但是,我需要一些指导来解决我的主要 XML 问题。

以后我可以得到循环内的节点值后,我想对每个房间的每件家具的总价格求和。

预期的最终 csv 结果:

Name,Furn_Id,a,b,c,d,e,f
House01,FUR00001,20000,60000,,70000,,110000
House01,FUR00002,20000,,100000,160000,90000,240000
House01,FUR00003,,40000,60000,,200000,240000

谢谢。

Getting the value of an attribute in XML

【问题讨论】:

  • 1. 除了房子还能有更多吗? 2. 每个房子都有完全相同的“房间”(a,b,c,d,e,f)吗? 3. 您将使用哪种 XSLT 处理器?
  • @michael.hor257k 1.会有超过 1 个房子 2.是的,完全相同的房间 (a,b,c,d,e,f) 3. XSLT 1.0
  • 但是具体是哪个 XSLT 1.0 处理器?如果您的处理器支持,您可以在此处使用扩展功能。
  • 我认为是 XPath?我没有配置任何东西,直接从jdk 1.8库中使用

标签: java xml csv xslt text-files


【解决方案1】:

这比看起来要复杂,因为您希望当前房屋中每个不同的FURN_ID 都有一行(或者至少从给定的示例中看起来是这样)。所以首要任务是找到这些不同的FURN_ID 值。

OTOH,如果每个房子都有完全相同的 6 个房间,那么在其匹配的列标题下显示每个家具的第二个任务要简单得多:

XSLT 1.0

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="text" encoding="UTF-8"/>

<xsl:key name="furn" match="Furniture" use="concat(@FURN_ID, '|', ../../@Name)" />

<xsl:template match="/FirstTag">
    <xsl:for-each select="SecondTag">
        <xsl:variable name="columns" select="*" />
        <xsl:variable name="unique-rows" select="*/Furniture[count(. | key('furn', concat(@FURN_ID, '|', ../../@Name))[1]) = 1]"/>
        <!-- header -->
        <xsl:text>Name,Furn_Id,a,b,c,d,e,f&#10;</xsl:text>
        <!-- rows -->
        <xsl:for-each select="$unique-rows">
            <xsl:value-of select="../../@Name"/>
            <xsl:text>,</xsl:text>
            <xsl:value-of select="@FURN_ID"/>
            <xsl:text>,</xsl:text>
            <xsl:variable name="id" select="@FURN_ID" />
            <xsl:for-each select="$columns">
                <xsl:variable name="cell" select="Furniture[@FURN_ID=$id]" />
                <xsl:if test="$cell">
                    <xsl:value-of select="$cell/@FURN_AMT * $cell/@price"/>
                </xsl:if>
                <xsl:if test="position()!=last()">
                    <xsl:text>,</xsl:text>
                </xsl:if>
            </xsl:for-each>
            <xsl:text>&#10;</xsl:text>
        </xsl:for-each>
     </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

应用于您的输入示例,结果将是:

Name,Furn_Id,a,b,c,d,e,f
House01,FUR00001,20000,60000,,70000,,110000
House01,FUR00002,20000,,100000,160000,90000,240000
House01,FUR00003,,40000,60000,,200000,240000

这与您的预期输出略有不同,但我相信它是正确的。

【讨论】:

  • 是的,我算错了 FUR00002 的房间 f 的价格..它应该是 240000 就像你的输出一样..这似乎是合法的!将在几秒钟内尝试。
猜你喜欢
  • 2013-06-20
  • 2013-10-04
  • 1970-01-01
  • 1970-01-01
  • 2017-09-09
  • 1970-01-01
  • 1970-01-01
  • 2019-02-02
相关资源
最近更新 更多