使用xslt样式表将xml文档转换为逗号分隔(CSV)文件 [英] convert xml document to comma delimited (CSV) file using xslt stylesheet

查看:188
本文介绍了使用xslt样式表将xml文档转换为逗号分隔(CSV)文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一些帮助,使用xslt样式表将xml文档转换为CSV文件。我试图使用以下xsl,我似乎不能得到它的权利。我想要我的逗号分隔文件包括列标题,后跟数据。我最大的问题是删除最后一个项目后的最后一个逗号,并插入回车,因此每组数据出现在单独的一行。我一直在使用XML记事本。





 < xsl:template match =/> 
< xsl:element name =table>
< xsl:apply-templates select =/ * / * [1]mode =header/>
< xsl:apply-templates select =/ * / *mode =row/>
< / xsl:element>
< / xsl:template>

< xsl:template match =*mode =header>
< xsl:element name =tr>
< xsl:apply-templates select =./*mode =column/>
< / xsl:element>
< / xsl:template>

< xsl:template match =*mode =row>
< xsl:element name =tr>
< xsl:apply-templates select =./*mode =node/>
< / xsl:element>
< / xsl:template>

< xsl:template match =*mode =column>
< xsl:element name =th>
< xsl:value-of select =translate(name(。),'qwertyuiopasdfghjklzxcvbnm _','QWERTYUIOPASDFGHJKLZXCVBNM')/>
< / xsl:element>,
< / xsl:template>

< xsl:template match =*mode =node>
< xsl:element name =td>
< xsl:value-of select =。 />
< / xsl:element>,
< / xsl:template>

解决方案>

我使用这个简单的XSLT将XML转换为CSV;它假定根节点的所有子节点都是CSV中的行,将根的第一个子节点的元素名称作为字段名称。

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

< xsl:template match =/>
< xsl:for-each select =* / * [1] / *>
< xsl:value-of select =name()/>
< xsl:if test =not(position()= last())>,< / xsl:if>
< / xsl:for-each>
< xsl:text>&#10;< / xsl:text>
< xsl:apply-templates select =* / *mode =row/>
< / xsl:template>

< xsl:template match =*mode =row>
< xsl:apply-templates select =*mode =data/>
< xsl:text>&#10;< / xsl:text>
< / xsl:template>

< xsl:template match =*mode =data>
< xsl:choose>
< xsl:when test =contains(text(),',')>
< xsl:text>& quot;< / xsl:text>
< xsl:call-template name =doublequotes>
< xsl:with-param name =textselect =text()/>
< / xsl:call-template>
< xsl:text>& quot;< / xsl:text>
< / xsl:when>
< xsl:otherwise>
< xsl:value-of select =。 />
< / xsl:otherwise>
< / xsl:choose>
< xsl:if test =position()!= last()>,< / xsl:if>
< / xsl:template>

< xsl:template name =doublequotes>
< xsl:param name =text/>
< xsl:choose>
< xsl:when test =contains($ text,'& quot;'')>
< xsl:value -of select =concat(substring-before($ text,'& quot;'),'& quot;& quot;')/>
< xsl:call-template name =doublequotes>
< xsl:with-param name =textselect =substring-after($ text,'& quot;')/>
< / xsl:call-template>
< / xsl:when>
< xsl:otherwise>
< xsl:value-of select =$ text/>
< / xsl:otherwise>
< / xsl:choose>
< / xsl:template>
< / xsl:stylesheet>

所以这个XML:

 < csv> 
< row>
< field1> foo< / field1>
< field2> bar< / field2>
< / row>
< row>
< field1> foo,2< / field1>
< field2> bar,2< / field2>
< / row>
< / csv>

转换为:

  field1,field2 
foo,bar
foo,2,bar,2

不知道这是否有帮助,这取决于你的XML是如何布局的。



彻底转换:

 <?xml version =1.0encoding =utf-8?> 
< xsl:stylesheet version =1.0xmlns:xsl =http://www.w3.org/1999/XSL/Transform>
< xsl:key name =fieldmatch = / * / * / *use =name()/>
< xsl:output method =text/>

< xsl:template match = />
< xsl:for-each select =* / * / * [generate-id()= generate-id(key('field',name())[ >
< xsl:value-of select =name()/>
< xsl:if test =position()!= last()> xsl:if>
< / xsl:for-each>
< xsl:text>&#10;< / xsl:text>
< xsl:apply-templates select =* / *mode =row/>
< / xsl:template>

< xsl:template match =*mode =row> ;
< xsl:variable name =rowselect =*/>
< xsl:for-each select =/ * / * / * [generate-id()= generate-id(key('field',name())[1])]>
< xsl:variable name =nameselect =name()/>
< xsl:apply-templates select =$ row [name()= $ name]mode =data/>
< xsl:if test =position()!= last()>,< / xsl:if>
< / xsl:for-each>
< xsl:text>&#10;< / xsl:text>
< / xsl:template>

< xsl:template match =*mode =data>
< xsl:choose>
< xsl:when test =contains(text(),',')>
< xsl:text>& quot;< / xsl:text>
< xsl:call-template name =doublequotes>
< xsl:with-param name =textselect =text()/>
< / xsl:call-template>
< xsl:text>& quot;< / xsl:text>
< / xsl:when>
< xsl:otherwise>
< xsl:value-of select =。 />
< / xsl:otherwise>
< / xsl:choose>
< xsl:if test =position()!= last()>,< / xsl:if>
< / xsl:template>

< xsl:template name =doublequotes>
< xsl:param name =text/>
< xsl:choose>
< xsl:when test =contains($ text,'& quot;'')>
< xsl:value -of select =concat(substring-before($ text,'& quot;'),'& quot;& quot;')/>
< xsl:call-template name =doublequotes>
< xsl:with-param name =textselect =substring-after($ text,'& quot;')/>
< / xsl:call-template>
< / xsl:when>
< xsl:otherwise>
< xsl:value-of select =$ text/>
< / xsl:otherwise>
< / xsl:choose>
< / xsl:template>
< / xsl:stylesheet>

这将在CSV中为所有rows中存在的所有标记名称创建一个列,并填充每一行中相应的列。


I need some assistance converting an xml document to a CSV file using an xslt stylesheet. I am trying to use the following xsl and I can't seem to get it right. I want my comma delimited file to include column headings, followed by the data. My biggest issues are removing the final comma after the last item and inserting a carriage return so each group of data appears on a separate line. I have been using XML Notepad.

  <xsl:template match="/">
        <xsl:element name="table">
              <xsl:apply-templates select="/*/*[1]" mode="header" />
              <xsl:apply-templates select="/*/*" mode="row" />
        </xsl:element>
  </xsl:template>

  <xsl:template match="*" mode="header">
        <xsl:element name="tr">
              <xsl:apply-templates select="./*" mode="column" />
        </xsl:element>
  </xsl:template>

  <xsl:template match="*" mode="row">
        <xsl:element name="tr">
              <xsl:apply-templates select="./*" mode="node" />
        </xsl:element>
  </xsl:template>

  <xsl:template match="*" mode="column">
        <xsl:element name="th">
              <xsl:value-of select="translate(name(.),'qwertyuiopasdfghjklzxcvbnm_','QWERTYUIOPASDFGHJKLZXCVBNM ')" />
        </xsl:element>,
  </xsl:template>

  <xsl:template match="*" mode="node">
        <xsl:element name="td">
              <xsl:value-of select="." />
        </xsl:element>,
  </xsl:template> 

解决方案

I use this to simple XSLT to convert XML to CSV; it assumes all child nodes of the root node are to be rows in the CSV, taking the element names of the first child of the root to be field names.

<?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:for-each select="*/*[1]/*">
      <xsl:value-of select="name()" />
      <xsl:if test="not(position() = last())">,</xsl:if>
    </xsl:for-each>
    <xsl:text>&#10;</xsl:text>
    <xsl:apply-templates select="*/*" mode="row"/>
  </xsl:template>

  <xsl:template match="*" mode="row">
    <xsl:apply-templates select="*" mode="data" />
    <xsl:text>&#10;</xsl:text>
  </xsl:template>

  <xsl:template match="*" mode="data">
    <xsl:choose>
      <xsl:when test="contains(text(),',')">
        <xsl:text>&quot;</xsl:text>
        <xsl:call-template name="doublequotes">
          <xsl:with-param name="text" select="text()" />
        </xsl:call-template>
        <xsl:text>&quot;</xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="." />
      </xsl:otherwise>
    </xsl:choose>
    <xsl:if test="position() != last()">,</xsl:if>
  </xsl:template>

  <xsl:template name="doublequotes">
    <xsl:param name="text" />
    <xsl:choose>
      <xsl:when test="contains($text,'&quot;')">
        <xsl:value-of select="concat(substring-before($text,'&quot;'),'&quot;&quot;')" />
        <xsl:call-template name="doublequotes">
          <xsl:with-param name="text" select="substring-after($text,'&quot;')" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$text" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

So this XML:

<csv>
  <row>
    <field1>foo</field1>
    <field2>ba"r</field2>
  </row>
  <row>
    <field1>foo,2</field1>
    <field2>bar,"2</field2>
  </row>
</csv>

Converts to:

field1,field2
foo,ba"r
"foo,2","bar,""2"

Not sure if this helps though, it depends how your XML is laid out.

Edit: Here's a more thorough transform:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:key name="field" match="/*/*/*" use="name()" />
  <xsl:output method="text"/>

  <xsl:template match="/">
    <xsl:for-each select="*/*/*[generate-id() = generate-id(key('field',name())[1])]">
      <xsl:value-of select="name()" />
      <xsl:if test="position() != last()">,</xsl:if>
    </xsl:for-each>
    <xsl:text>&#10;</xsl:text>
    <xsl:apply-templates select="*/*" mode="row"/>
  </xsl:template>

  <xsl:template match="*" mode="row">
    <xsl:variable name="row" select="*" />
    <xsl:for-each select="/*/*/*[generate-id() = generate-id(key('field',name())[1])]">
      <xsl:variable name="name" select="name()" />
      <xsl:apply-templates select="$row[name()=$name]" mode="data" />
      <xsl:if test="position() != last()">,</xsl:if>
    </xsl:for-each>
    <xsl:text>&#10;</xsl:text>
  </xsl:template>

  <xsl:template match="*" mode="data">
    <xsl:choose>
      <xsl:when test="contains(text(),',')">
        <xsl:text>&quot;</xsl:text>
        <xsl:call-template name="doublequotes">
          <xsl:with-param name="text" select="text()" />
        </xsl:call-template>
        <xsl:text>&quot;</xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="." />
      </xsl:otherwise>
    </xsl:choose>
    <xsl:if test="position() != last()">,</xsl:if>
  </xsl:template>

  <xsl:template name="doublequotes">
    <xsl:param name="text" />
    <xsl:choose>
      <xsl:when test="contains($text,'&quot;')">
        <xsl:value-of select="concat(substring-before($text,'&quot;'),'&quot;&quot;')" />
        <xsl:call-template name="doublequotes">
          <xsl:with-param name="text" select="substring-after($text,'&quot;')" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$text" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

This one will create a column in your CSV for all tag names that exist in all 'rows', and populate the appropriate column in each row.

这篇关于使用xslt样式表将xml文档转换为逗号分隔(CSV)文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆