2015-11-27 24 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