使用xsl将xml属性导出到csv

时间:2017-10-02 14:02:49

标签: xml csv xslt saxon

我想使用xsl将xml属性导出到csv,但我遇到了这个问题:

<root>
  <tag id="1">
     <itemA  id="930" dummyAttr1="bla" dummyAttr2="bla bla" dummyAttr3="bla bla bla" />
     <itemA  id="931" dummyAttr1="bla" dummyAttr3="bla bla bla" />
     <itemA  id="932" dummyAttr2="bla bla" dummyAttr3="bla bla bla" />
     <itemA  id="933" dummyAttr4="another bla" dummyAttr3="bla bla bla" />
  </tag>
  <tag id="2">
     <itemA  id="940" dummyAttr1="lorem" dummyAttr2="ipsum" />
     <itemA  id="941" dummyAttr1="dolor" dummyAttr3="sit" />
     <itemA  id="942" dummyAttr3="amet" />
  </tag>
</root>

我想要在csv标头中设置动态属性,然后我想在右侧标题下添加我的属性值。

我尝试了这样的事情没有成功

    <?xml version="1.0"?>
   <xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:saxon="http://saxon.sf.net/"
    exclude-result-prefixes="#all">
        <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
        <xsl:template name="header" >
            <xsl:for-each-group select="//itemA/@*" group-by="name(.)">
                <xsl:value-of select="name(.)"/>
                <xsl:choose>
                    <xsl:when test="position() != last()">
                        <xsl:text>,</xsl:text>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:text>&#xA;</xsl:text>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:template>
        <xsl:template name="values" >
            <xsl:for-each-group select="//itemA/@*" group-by="name(.)">
                <xsl:value-of select="."/>
                <xsl:choose>
                    <xsl:when test="position() != last()">
                        <xsl:text>,</xsl:text>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:text>&#xA;</xsl:text>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:template>
        <xsl:template match="/">
            <xsl:call-template name="header"/>
            <xsl:for-each select="//itemA">
                <xsl:for-each select="./@*">
                    <xsl:variable name="test">
                        <xsl:call-template name="values"/>
                    </xsl:variable>
                    <xsl:value-of select="$test"/>
                </xsl:for-each>
                <xsl:text>&#xA;</xsl:text>
            </xsl:for-each>
        </xsl:template>
    </xsl:stylesheet>

输出必须如下:

id,dummyAttr1,dummyAttr2,dummyAttr3,dummyAttr4
930,bla,bla bla,bla bla bla,
931,bla,,bla bla bla,
932,,bla bla,bla bla bla,
933,,,bla bla bla,another bla
940,lorem,ipsum,,
941,dolor,,sit,
942,,,amet,

谢谢

1 个答案:

答案 0 :(得分:0)

我认为以下情况应该:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    exclude-result-prefixes="xs math"
    version="3.0">

    <xsl:output method="text"/>

    <xsl:variable name="columns" as="xs:string*" select="distinct-values(//itemA/@*/name())"/>

    <xsl:template match="/">
        <xsl:value-of select="$columns" separator=","/>
        <xsl:text>&#10;</xsl:text>
        <xsl:apply-templates select="//itemA"/>
    </xsl:template>

    <xsl:template match="itemA">
        <xsl:value-of select="for $col in $columns return (@*[name() = $col], '')[1]" separator=","/>
        <xsl:text>&#10;</xsl:text>
    </xsl:template>

</xsl:stylesheet>

或者也许是最后一个模板

<xsl:template match="itemA">
    <xsl:value-of select="for $col in $columns return @*[name() = $col] || ''" separator=","/>
    <xsl:text>&#10;</xsl:text>
</xsl:template>