2016-03-03 15 views
0

我無法解決如何將下面的xml文件轉換爲csv。 它有2個關鍵元素(虛擬磁盤)與可變數量的分組元素。 這是我的嘗試。任何幫助理解:-)XML到CSV與可變數量的分組元素

file.xml

<?xml version="1.0" encoding="UTF-8"?> 
<raid> 
<system> 
<name>ARRAY1</name> 
<status>ok</status> 
<network> 
<ip1>192.168.15.9</ip1> 
<ip2>192.168.15.10</ip2> 
<gateway1>192.168.15.254</gateway1> 
<netmask2>255.255.255.0</netmask2> 
</network> 
<name>a6180-1</name> 
<vdisk> 
<vdisk_idx>SITE-A</vdisk_idx> 
<volume_name>data1</volume_name> 
<volume_id>5DF4</volume_id> 
<volume_size>21474836480</volume_size> 
<volume_name>home1</volume_name> 
<volume_id>F0DD</volume_id> 
<volume_size>32212254720</volume_size> 
<volume_name>data2</volume_name> 
<volume_id>F251</volume_id> 
<volume_size>161061273600</volume_size> 
<volume_name>archive</volume_name> 
<volume_id>F252</volume_id> 
<volume_size>161061273600</volume_size> 
</vdisk> 
<vdisk> 
<vdisk_idx>SITE-B</vdisk_idx> 
<volume_name>data</volume_name> 
<volume_id>A33B</volume_id> 
<volume_size>150323855360</volume_size> 
<volume_name>home</volume_name> 
<volume_id>9E80</volume_id> 
<volume_size>64424509440</volume_size> 
<volume_name>Archive</volume_name> 
<volume_id>6D30</volume_id> 
<volume_size>42951770112</volume_size> 
</vdisk> 
<other> 
<cruft> 
</cruft> 
</other> 
</system> 
</raid> 

file.xsl

<?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" /> 
    <xsl:variable name="delimiter" select="','" /> 
    <!-- define an array containing the fields we are interested in --> 
    <xsl:variable name="fieldArray"> 
    <field>volume_name</field> 
    <field>vdisk_idx</field> 
    <field>volume_size</field> 
    <field>volume_id</field> 
    </xsl:variable> 
    <xsl:param name="fields" select="document('')/*/xsl:variable[@name='fieldArray']/*" /> 
<xsl:template match="/"> 
    <!-- output the header row --> 
    <xsl:for-each select="$fields"> 
     <xsl:if test="position() != 1"> 
     <xsl:value-of select="$delimiter"/> 
     </xsl:if> 
     <xsl:value-of select="." /> 
    </xsl:for-each> 
    <!-- output newline --> 
    <xsl:text>&#xa;</xsl:text> 
    <xsl:apply-templates select="raid/system/vdisk"/> 
    </xsl:template> 
    <xsl:template match="vdisk/vdisk_idx"> 
    <xsl:variable name="currIDX" select="." /> 
    </xsl:template>  
    <xsl:template match="vdisk"> 
    <xsl:variable name="currNode" select="." /> 
    <!-- output the data row --> 
    <!-- loop over the field names and find the value of each one in the xml --> 
    <xsl:for-each select="$fields"> 
     <xsl:if test="position() != 1"> 
     <xsl:value-of select="$delimiter"/> 
     </xsl:if> 
     <xsl:value-of select="$currNode/*[name() = current()]" /> 
    </xsl:for-each> 
    <!-- output newline --> 
    <xsl:text>&#xa;</xsl:text> 
    </xsl:template> 
</xsl:stylesheet> 

使用命令行XSLT處理器(xsltproc的)

xsltproc的file.xsl file.xml

volume_name,vdisk_idx,volume_size,volume_id 
data1,SITE-A,21474836480,5DF4 
data,SITE-B,150323855360,A33B 

但我想/預期:

volume_name,vdisk_idx,volume_size,volume_id 
data1,SITE-A,20.000 GB,5DF4 
home1,SITE-A,30.000 GB,F0DD 
data2,SITE-A,150.000 GB,F252 
archive,SITE-A,150.000 GB,F251 
data,SITE-B,140.000 GB,A33B 
home,SITE-B,60.000 GB,9E80 
Archive,SITE-B,40.002 GB,6D30 

回答

0

我建議你試試這樣說:

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

<xsl:template match="/raid"> 
    <xsl:text>volume_name,vdisk_idx,volume_size,volume_id&#10;</xsl:text> 
    <xsl:for-each select="system/vdisk/volume_name"> 
     <xsl:value-of select="."/> 
     <xsl:text>,</xsl:text> 
     <xsl:value-of select="../vdisk_idx"/> 
     <xsl:text>,</xsl:text> 
     <xsl:value-of select="format-number(following-sibling::volume_size[1] div 1000000000, '0.000 GB')"/> 
     <xsl:text>,</xsl:text> 
     <xsl:value-of select="following-sibling::volume_id[1]"/> 
     <xsl:text>&#10;</xsl:text> 
    </xsl:for-each> 
</xsl:template> 

</xsl:stylesheet>