2015-11-27 151 views
0

我是XSLT新手,一直在努力解决以下问题。我很感激能否帮助我如何解决这个问题。将未知XML转换为CSV的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>[email protected]</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,[email protected] 

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 

我想相关的元素在一行出现在上面。

感谢

+1

这是不可能写一个通用的XSLT样式表,将适合任何* * XML输入。如果你想产生一个有意义的结果,你必须提供一些约束条件。在你的例子中,你为'teacher'开始一个新的“表”,但不是'joined'。一个真正的通用样式表将无法做出这样的区分。 –

回答

2

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

<?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> 
+0

谢谢亚历山大。我会试试看看它是如何发展的。结果会回来。 – Adia

+0

感谢这工作很好。顺便说一句,如果我想用它的显示名称替换一个元素名称,我该怎么做?我试过了:教师助理在第一个之后,但它会同时打印元素名称和显示名称。我想用显示名称替换元素名称。如果元素名称等于teacherAssistant,则将其替换为Teacher assistant。再次感谢。 – Adia

+0

@Adia - 查看更新。 –

0

您可以使用身份模板(如在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 
[email protected] 

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 
[email protected]@medi.com 

(请注意,我不得不把最终在你的XML

+0

谢谢malarres。我知道复制,而这正是我从XML文件获取副本的过程。问题是XML文件每次都根据用户从表单中选择而改变。元素每次都有所不同,但结构几乎相同。 – Adia

+0

我误解了这个问题。所以,无论当前输入如何,你都希望得到相同的输出格式,对吧?我们可以指望有一些固定的节点名称吗? ... – malarres

+0

是的我想要相同的输出格式。输入格式也具有相同的结构,只是某些元素名称可能不同;例如曾经可以是,下次可以是。或者有时某些元素或子元素可能在一个输入中,而在下一个输入中不存在。 – Adia