我是 XSLT 和 XML 的新手。我一直在浏览教程和 stackoverflow 示例并学习很多新东西。
目前我正在尝试在 XML 文件上应用 XSLT 将其转换为 CSV。我想要实现的是,我在 XML 文件中有一些信息,我想提取这些信息。默认情况下,CSV 文件将包含一些信息,我将在 XSLT 中传递这些信息。
此外,我还使用了我很快学会的基本 XSLT 语法,我确信这是最糟糕的方法。如果有人能指导我如何改进这个解决方案,我将不胜感激。
我遇到的问题如下:
信息的格式不正确,它被打印在新行上,除非我指定新行,否则我不希望出现这种情况。另外,如果我不缩进 XSLT 文件,那么信息可以保留为单个,但代码看起来很困惑,我确信有一些简单的方法可以做到这一点。
每个人都会有一些许可证,我想在 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>
</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>
</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>
</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/