【问题标题】:XSLT to convert unknown XML to CSVXSLT 将未知的 XML 转换为 CSV
【发布时间】:2016-03-01 13:41:32
【问题描述】:

我是 XSLT 的新手,一直在努力解决以下问题。如果有人可以帮助我解决这个问题,我将不胜感激。

这是我的 XML 文件,但元素名称每次都可能不同。 XML 是在运行时创建的。基本上我不知道 XML 文件中的所有元素。可能有或多或少的元素,但基本上具有以下结构:

    <University>
    <language>en</language>
    <name>Medi University</name>
    <location>Rome</location>
    <country>Italy</country>
    <member>
        <teacher>
                <name>John Sting</name>
                <joined>
                    <time>
                    <start/>
                        <end/>
                     </time>
                    <valid>true</valid>
                </joined>
                <name>Paul Ironman</name>
                <joined>
                    <time>
                    <start/>
                        <end/>
                     </time>
                    <valid>true</valid>
                </joined>
        </teacher>
        <teacherAssistant>
               <name>Luna Tutti</name>
                <joined>
                    <time>
                         <start>1.9.2015</start>
                        <end></end>
                    </time>
                    <valid>true</valid>
                </joined>
        </teacherAssistant>
     </member>
    <telephone>7538476398754</telephone>
    <email>medi@medi.com</email>
</University>

我有一个试图转换它的 XSLT 文件。正如我所说,XML 文件是在运行时创建的,我不知道 XML 内容。

 <xsl:template match="/">
      <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="*">
   <xsl:value-of select="name()"/>
      <xsl:value-of select="text()"/>
      <xsl:if test="*">
          <xsl:apply-templates/>
      </xsl:if>
  </xsl:template>
</xsl:stylesheet>

上面的代码像这样打印 CSV 文件:

elemenNameelementValue
elemenName2elementValue2
elemenName3elementValue3

等等。

我想要的是像下面这样的:

University

language, name, location, country,telephone, email
english, Medi, Rome,Italy,7538476398754,medi@medi.com

Teacter

name, joined, time, start,end,valid,
John Sting, , , , ,true
Paul Ironman, , , , , true

Teacher Assistant

name, joined, time, start,end,valid,
Luna Tutti, , ,1.9.2015, , true 

我希望相关元素像上面一样出现在一行上。

谢谢

【问题讨论】:

  • 不可能编写适合任何 XML 输入的通用XSLT 样式表。如果您想产生有意义的结果,您必须提供一些约束。在您的示例中,您为teacher 创建了一个新“表”,但不是为joined。真正通用的样式表无法区分。

标签: xml csv xslt


【解决方案1】:

试试这个真正通用的样式表

<?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" omit-xml-declaration="yes" indent="no"/>

    <xsl:template match="node()">
        <xsl:value-of select="name()"/>
        <xsl:text>&#xA;</xsl:text>
        <xsl:call-template name="loop"/>
    </xsl:template>

    <xsl:template name="loop">
        <!-- Output headers -->
        <xsl:for-each select="./*[count(*) = 0]">
            <xsl:value-of select="name()"/>
            <xsl:if test="position() != last()">
                <xsl:text>,</xsl:text>
            </xsl:if>
        </xsl:for-each>
        <xsl:text>&#xA;</xsl:text>

        <!-- Output values -->
        <xsl:for-each select="./*[count(*) = 0]">
            <xsl:value-of select="."/>
            <xsl:if test="position() != last()">
                <xsl:text>,</xsl:text>
            </xsl:if>
        </xsl:for-each>
        <xsl:text>&#xA;</xsl:text>

        <!-- Process nodes having childs -->
        <xsl:for-each select="./*[count(*) != 0]">
            <xsl:value-of select="name()"/>
            <xsl:text>&#xA;</xsl:text>
            <xsl:call-template name="loop"/>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

正如 michael.hor257k 所提到的,没有一些限制,新表会为每个具有子节点的节点启动。


试试这个替换

<!-- Process nodes having childs -->
<xsl:for-each select="./*[count(*) != 0]">
    <xsl:choose>
        <xsl:when test="name() = 'teacher'">
            <xsl:text>Teacher</xsl:text>
        </xsl:when>
        <xsl:when test="name() = 'teacherAssistant'">
            <xsl:text>Teacher Assistant</xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="name()"/>
        </xsl:otherwise>
    </xsl:choose>

    <xsl:text>&#xA;</xsl:text>
    <xsl:call-template name="loop"/>
</xsl:for-each>

【讨论】:

  • 谢谢亚历山大。我会试试这个,看看效果如何。会带着结果返回这里。
  • 谢谢,效果很好。顺便说一句,如果我想用它的显示名称替换元素名称,我该怎么做?我试过这个:Teacher Assistant 在第一个 之后,但它打印元素名称和显示名称。我想用显示名称替换元素名称。就像元素名称等于teacherAssistant 一样,将其替换为Teacher Assistant。再次感谢。
  • 感激不尽。那很完美。再次感谢。
【解决方案2】:

您可以使用身份模板(如Using XSLT to copy all nodes in XML, with support for special cases)并从那里开始工作。

举个例子,用这段代码

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">    
<xsl:template match="@*|node()">
        <xsl:value-of select="."/>
            <xsl:apply-templates select="@*|node()"/>
    </xsl:template>

</xsl:stylesheet>

输出是:

<?xml version="1.0" encoding="UTF-8"?>
en
Medi University
Rome
Italy


            John Sting





                true

            Paul Ironman





                true



           Luna Tutti


                     1.9.2015


                true



7538476398754
medi@medi.com

enen
Medi UniversityMedi University
RomeRome
ItalyItaly


            John Sting





                true

            Paul Ironman





                true



           Luna Tutti


                     1.9.2015


                true




            John Sting





                true

            Paul Ironman





                true


            John StingJohn Sting





                true








                truetrue

            Paul IronmanPaul Ironman





                true








                truetrue



           Luna Tutti


                     1.9.2015


                true


           Luna TuttiLuna Tutti


                     1.9.2015


                true


                     1.9.2015


                     1.9.20151.9.2015


                truetrue



75384763987547538476398754
medi@medi.commedi@medi.com

(请注意,我必须在您的 XML 中添加final

【讨论】:

  • 谢谢马拉雷斯。我知道复制,这就是我从 XML 文件中获取副本所做的事情。问题是 XML 文件每次都会根据用户从表单中的选择而更改。元素每次都不同,但结构几乎相同。
  • 我误解了这个问题。因此,无论当前输入如何,您都希望获得相同的输出格式,对吧?我们可以指望有一些固定的节点名称吗? ...
  • 是的,我想要相同的输出格式。输入格式也具有相同的结构,只是某些元素名称可能不同;例如,一次可能是 ,下一次可能是 。或者有时某些元素或子元素可能在一个输入中而在下一个输入中不存在。
猜你喜欢
  • 1970-01-01
  • 2019-02-02
  • 2014-07-20
  • 2017-05-23
  • 2011-10-28
相关资源
最近更新 更多