【问题标题】:XML-XSLT-CSV transformationXML-XSLT-CSV 转换
【发布时间】:2016-02-08 11:46:34
【问题描述】:

我正在尝试通过 XSLT 将我的 XML 文档转换为 CSV。到目前为止无法达到预期的效果。

XML 如下:

<projects>
  <project>
    <name>Shockwave</name>
    <language>Ruby</language>
    <owner>Brian May</owner>
    <state>New</state>
    <startDate>31/10/2008 0:00:00</startDate>
  </project>
  <project>
    <name>Other</name>
    <language>Erlang</language>
    <owner>Takashi Miike</owner>
    <state> Canceled </state>
    <startDate>07/11/2008 0:00:00</startDate>
  </project>
  </projects>

XSLT 如下:

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

  <xsl:strip-space elements="*" />

  <xsl:template match="/*/child::*">
    <xsl:for-each select="child::*">
      <xsl:if test="position() != last()">
        <xsl:value-of select="normalize-space(.)"/>,
      </xsl:if>
      <xsl:if test="position()  = last()">
        <xsl:value-of select="normalize-space(.)"/><xsl:text>&#xD;</xsl:text>
      </xsl:if>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

输出如下:

虽然要求转换为 CSV,如下所示: 标题是第一行。然后在 startDate 之后换行。

姓名、语言、所有者、州、开始日期

Shockwave, Ruby, Brian May,New,31/10/2008 0:00:00

Other,Erlang,Takashi Miike,Cancelled,07/11/2008 0:00:00

【问题讨论】:

    标签: xml csv xslt export-to-csv


    【解决方案1】:

    问题出在这句话上

      <xsl:if test="position() != last()">
        <xsl:value-of select="normalize-space(.)"/>,
      </xsl:if>
    

    你正在输出一个逗号,但逗号后面的换行符也会被输出。如果整个文本节点都是空白,XSLT 只会忽略空白。一旦你包含一个非空白字符,它也会输出你的缩进!

    所以,你需要把它改成这个……

      <xsl:if test="position() != last()">
        <xsl:value-of select="normalize-space(.)"/><xsl:text>,</xsl:text>
      </xsl:if>
    

    话虽如此,您可以进一步简化您的 XSLT。试试这个

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="text" encoding="iso-8859-1"/>
    
      <xsl:strip-space elements="*" />
    
      <xsl:template match="/*/child::*">
        <xsl:for-each select="child::*">
          <xsl:if test="position() > 1">
            <xsl:text>,</xsl:text>
          </xsl:if>
          <xsl:value-of select="normalize-space(.)"/>
        </xsl:for-each>
        <xsl:text>&#xD;</xsl:text>
      </xsl:template>
    </xsl:stylesheet>
    

    编辑:如果您想输出标题行,请将此模板添加到 XSLT

    <xsl:template match="/*">
       <xsl:for-each select="*[1]/*">
          <xsl:if test="position() > 1">
            <xsl:text>,</xsl:text>
          </xsl:if>
          <xsl:value-of select="local-name()"/>
       </xsl:for-each>
       <xsl:text>&#xD;</xsl:text>
       <xsl:apply-templates />
    </xsl:template>
    

    【讨论】:

    • 酷。有效。有什么方法可以在不进行硬编码的情况下添加标题?
    • 我在回答中添加了一个示例。
    • 顺便说一句,在除第一行之外的每一行之前输出逗号可能(取决于处理器)效率更高,而不是在除最后一行之外的每一行之后。测试你是否在最后一行可能需要大量昂贵的前瞻。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-02
    • 2013-02-20
    • 2017-05-23
    • 2011-10-28
    相关资源
    最近更新 更多