XML 到 CSV 应用 XSLT(格式问题、逻辑错误)

标签 xml csv xslt xslt-1.0

我是 XSLT 和 XML 的新手。我一直在浏览教程和 stackoverflow 示例并学习很多新东西。

目前我正在尝试在 XML 文件上应用 XSLT 将其转换为 CSV。我想要实现的是,我在 XML 文件中有一些信息,我想提取这些信息。默认情况下,CSV 文件将包含一些信息,我将在 XSLT 中传递这些信息。

此外,我还使用了我很快学会的基本 XSLT 语法,我确信这是最糟糕的方法。如果有人能指导我如何改进这个解决方案,我将不胜感激。

我遇到的问题如下:

  1. 信息的格式不正确,它被打印在新行上,除非我指定新行,否则我不希望出现这种情况。另外,如果我不缩进 XSLT 文件,那么信息可以保留为单个,但代码看起来很困惑,我确信有一些简单的方法可以做到这一点。

  2. 每个人都会有一些许可证,我想在 for-each 循环中阅读这些许可证,但我很困惑如何做到这一点。就好像这个人没有一些许可证一样,默认情况下我希望它为空。目前,在此示例中我使用 5 个状态。

这是我用来测试的 xml 文件。

<?xml version="1.0" encoding="UTF-8"?>
<People>
<Person>
    <required-tag1>some-information</required-tag1>
    <required-tag2>some-information</required-tag2>
    <first-name>Mike</first-name>
    <last-name>Hewitt</last-name>
    <licenses>
        <license>
            <state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">IL</state>
        </license>
    </licenses>
</Person>
<Person>
    <required-tag1>some-information</required-tag1>
    <required-tag2>some-information</required-tag2>
    <first-name>John</first-name>
    <last-name>Jhonny</last-name>
    <licenses>
        <license>
            <state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">NY</state>
        </license>
    </licenses>
</Person>
<Person>
    <required-tag1>some-information</required-tag1>
    <required-tag2>some-information</required-tag2>
    <first-name>Xmen</first-name>
    <last-name>Bat</last-name>
    <licenses>
        <license>
            <state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">AK</state>
        </license>
        <license>
            <state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">CA</state>
        </license>
        <license>
            <state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">IL</state>
        </license>
        <license>
            <state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">NY</state>
        </license>
        <license>
            <state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">TX</state>
        </license>
    </licenses>
</Person>
</People>

我编写的XSLT如下:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:csv="csv:csv" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="UTF-8" method="text"/>
<xsl:template match="/People">First Name,Last Name,AK,CA,IL,NY,TX,default value1,required-tag1,required-tag2,default value2,default value3
    <xsl:for-each select="Person">
        <xsl:value-of select="first-name"/>, <xsl:value-of select="last-name"/>,<xsl:choose>
    <xsl:when test="licenses/license/state='AK'">
      <xsl:value-of select="licenses/license/state"/>,
    </xsl:when>
    <xsl:otherwise>NA,
    </xsl:otherwise></xsl:choose><xsl:choose>
    <xsl:when test="licenses/license/state='CA'">
      <xsl:value-of select="licenses/license/state"/>,
    </xsl:when>
    <xsl:otherwise>NA,
    </xsl:otherwise></xsl:choose><xsl:choose>
    <xsl:when test="licenses/license/state='IL'">
      <xsl:value-of select="licenses/license/state"/>,
    </xsl:when>
    <xsl:otherwise>NA,
    </xsl:otherwise></xsl:choose><xsl:choose>
    <xsl:when test="licenses/license/state='NY'">
      <xsl:value-of select="licenses/license/state"/>,
    </xsl:when>
    <xsl:otherwise>NA,
    </xsl:otherwise></xsl:choose><xsl:choose>
    <xsl:when test="licenses/license/state='TX'">
      <xsl:value-of select="licenses/license/state"/>,
    </xsl:when>
    <xsl:otherwise>NA,
    </xsl:otherwise></xsl:choose>DEFAULT VALUE1,<xsl:value-of select="required-tag1"/>,<xsl:value-of select="required-tag2"/>,DEFAULT VALUE2,DEFAULT VALUE3<xsl:text>&#xa;</xsl:text>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

我尝试在许可证的 for-each 循环中使用 for-each 循环,但对所有许可证执行了 5 次,如何执行条件来测试许可证状态 5 次并保持默认格式正确。

这就是我想要的输出方式:

First Name,Last Name,AK,CA,IL,NY,TX,default value1,required-tag1,required-tag2,default value2,default value3
Mike, Hewitt,NA,NA,IL,NA,NA,DEFAULT VALUE1,some-information,some-information,DEFAULT VALUE2,DEFAULT VALUE3
John, Jhonny,NA,NA,NA,NY,NA,DEFAULT VALUE1,some-information,some-information,DEFAULT VALUE2,DEFAULT VALUE3
Xmen, Bat,AK,CA,IL,NY,TX,DEFAULT VALUE1,some-information,some-information,DEFAULT VALUE2,DEFAULT VALUE3

我正在使用 XSLT 版本 1.0。

谢谢你的帮助。

最佳答案

对于新行的问题,请考虑您当前如何编写 NA 作为示例

<xsl:otherwise>NA,
</xsl:otherwise>

现在,如果你有这个......

<xsl:otherwise>
</xsl:otherwise>

那么 XSLT 根本不会输出新行。 xsl:otherwise 下有一个文本节点,但它是纯空白节点,因此被忽略。但是,一旦您向其中添加普通文本(例如 NA),XSLT 就会认为所有文本都很重要,并输出它(包括换行符)。它不会标准化任何空格。

解决方案是将所有此类文本包装在 xsl:text

<xsl:otherwise>
   <xsl:text>NA</xsl:text>
</xsl:otherwise>

至于你的逻辑问题,你目前正在这样做是为了检查状态

<xsl:when test="licenses/license/state='IL'">
  <xsl:value-of select="licenses/license/state"/>,
</xsl:when>

但是每个语句中 licenses/license/state 的使用之间存在细微差别。在 xsl:when 中,您询问“是否有具有此状态的许可证”,但在您的 xsl:value-of 中,它将获得列表中的第一个状态!

现在,你可以写这个

<xsl:when test="licenses/license/state='IL'">
  <xsl:value-of select="licenses/license[state='IL']/state"/>
  <xsl:text>,</xsl:text>
</xsl:when>

但这其实是多余的。最好将其简化为这样

<xsl:when test="licenses/license/state='IL'">
  <xsl:text>IL,</xsl:text>
</xsl:when>

还值得一提的是,您显然有很多重复的代码,因此您可以通过使用命名模板来删除其中的一些代码。

试试这个 XSLT 作为示例

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

<xsl:template match="/People">
  <xsl:text>First Name,Last Name,AK,CA,IL,NY,TX,default value1,required-tag1,required-tag2,default value2,default value3</xsl:text>
  <xsl:text>&#xa;</xsl:text>
    <xsl:for-each select="Person">
        <xsl:value-of select="first-name"/>
        <xsl:text>, </xsl:text>
        <xsl:value-of select="last-name"/>
        <xsl:text>, </xsl:text>
        <xsl:call-template name="state">
          <xsl:with-param name="stateCode" select="'AK'" />
        </xsl:call-template>
      <xsl:call-template name="state">
          <xsl:with-param name="stateCode" select="'CA'" />
        </xsl:call-template>
       <xsl:call-template name="state">
          <xsl:with-param name="stateCode" select="'IL'" />
        </xsl:call-template>
      <xsl:call-template name="state">
          <xsl:with-param name="stateCode" select="'NY'" />
        </xsl:call-template>
        <xsl:call-template name="state">
          <xsl:with-param name="stateCode" select="'TX'" />
        </xsl:call-template>
        <xsl:text>DEFAULT VALUE1,</xsl:text>
        <xsl:value-of select="required-tag1"/>
        <xsl:text>,</xsl:text>
        <xsl:value-of select="required-tag2"/>
        <xsl:text>,DEFAULT VALUE2,DEFAULT VALUE3</xsl:text>
        <xsl:text>&#xa;</xsl:text>
    </xsl:for-each>
</xsl:template>

<xsl:template name="state">
  <xsl:param name="stateCode" />
  <xsl:choose>
      <xsl:when test="licenses/license[state=$stateCode]">
        <xsl:value-of select="$stateCode"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:text>NA</xsl:text>
      </xsl:otherwise>
  </xsl:choose>
  <xsl:text>,</xsl:text>
</xsl:template>
</xsl:stylesheet>

这仍然是相当重复的,重复使用xsl:call-template。例如,如果您只需要 5 个固定状态,则可以将这些状态放入外部 XML 文档中,然后对其进行循环。但这将是另一个问题......

关于XML 到 CSV 应用 XSLT(格式问题、逻辑错误),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26128694/

相关文章:

c# - 通过序列化更新现有的 XML 文件

android - 在我的手机上运行应用程序时不显示垂直线 View

python - 这是什么时间格式? 20151104101700-0800

java - csvWriter java : Create csv with multiple pages

r - 使用 R 编写 .mat 文件没有给出正确的输出?

java - 在建立数据源连接之前获取 URL 值

xslt - 使用 XSLT 将数据从一个 XML 文档复制到另一个 XML 文档

xml - 使用 XSLT 创建基于双重条件的元素

xslt - 身份模板困惑

python - 在 python 中获取空 CSV