2012-07-26 141 views
0

這裏提取從XML文件中的值到字段分隔符格式示例文件,我們需要值轉換爲分隔符格式的文件: -使用UNIX腳本/命令

的test.xml

<?xml version="1.0" encoding="UTF-8" ?> 
<testjar> 

<testable> 
<trigger>Trigger1</trigger> 
<message>2012-06-14T00:03.54</message> 
<sales-info> 
<san-a>no</san-a> 
<san-b>no</san-b> 
<san-c>no</san-c> 
</sales-info> 
</testable> 


    <testable> 
    <trigger>Trigger2</trigger> 
    <message>2012-06-15T00:03.54</message> 
    <sales-info> 
    <san-a>yes</san-a> 
    <san-b>yes</san-b> 
    <san-c>no</san-c> 
    </sales-info> 
</testable> 

</testjar> 

每個記錄應該從新線開始。樣本結果集應該是這樣的 sample.txt的

Trigger1|2012-06-14T00:03.54|no|no|no 
Trigger2|2012-06-15T00:03.54|yes|yes|no 

注: - xmlstarlet是不是我的服務器上安裝,是不是可以不xmlstarlet執行此?

+2

請修正''? – kev 2012-07-26 08:36:37

回答

1

如果您已經安裝xmlstarlet,你可以嘗試:命令

[email protected]$ xmlstarlet sel -t -m "//testable" -v trigger -o "|" -v message -o "|" -m sales-info -v san-a -o "|" -v san-b -o "|" -v san-c -n test.xml 
Trigger1|2012-06-14T00:03.54|no|no|no 
Trigger2|2012-06-15T00:03.54|yes|yes|no 

擊穿:

xmlstarlet sel -t 
    -m "//testable"  # match <testable> 
     -v trigger -o "|"  # print out value of <trigger> followed by | 
     -v message -o "|"  # print out value of <message> followed by | 
     -m sales-info   # match <sales-info> 
     -v san-a -o "|"  # print out value of <san-a> followed by | 
     -v san-b -o "|"  # print out value of <san-b> followed by | 
     -v san-c    # print out value of <san-c> 
    -n     # print new line 
    test.xml    # INPUT XML FILE 

來定位內<testable>不同的標籤,你可以嘗試返回文本以下所有葉節點:

[email protected]$ xmlstarlet sel -t -m "//testable" -m "descendant::*[not(*)]" -v 'text()' -i 'not(position()=last())' -o '|' -b -b -n test.xml 
Trigger1|2012-06-14T00:03.54|no|no|no 
Trigger2|2012-06-15T00:03.54|yes|yes|no 

c ommand:

xmlstarlet sel -t 
    -m "//testable"       # match <testable> 
     -m "descendant::*[not(*)]"    # match all leaf nodes 
     -v 'text()'        # print text 
     -i 'not(position()=last())' -o '|'  # print | if not last item 
     -b -b         # break out of nested matches 
    -n          # print new line 
    test.xml        # INPUT XML FILE 

如果您沒有訪問xmlstarlet,那麼就查找您在您的處置有什麼其他的工具。其他選項包括xsltproc(請參閱mzjn's answer)和xpath

如果這些工具不可用,我會建議使用更高級別的語言(Python,Perl),它允許您訪問正確的XML庫。

雖然可以使用手動regex解析它,這樣的解決方案將是不理想特別是不一致的輸入。例如,下面的(假設你有gawksed)把你的輸入,並應吐出預期輸出:

[email protected]$ gawk 'match($0, />(.*)</, a){printf("%s|",a[1])} /<\/testable>/{print ""}' test.xml | sed 's/.$//' 
Trigger1|2012-06-14T00:03.54|no|no|no 
Trigger2|2012-06-15T00:03.54|yes|yes|no 

然而,這遭到慘敗,如果輸入格式的變化,因此不是一個解決方案,我一般會推薦

+0

在這裏捕捉是我的文件(xml頁面會增加或減少)會不斷變化..有一個命令可以處理這個問題嗎? – 2012-07-26 09:04:23

+0

你的意思是''中的標籤總是不一樣嗎? – 2012-07-26 09:15:24

+0

是的..但是我們可以在另一個文件中存儲tages,並在這裏獲取信息...我們可以管理這個..很大的問題是不幸的是我沒有xmlstarlet在我的服務器上:-(這可能沒有xmlstarlet? – 2012-07-26 09:18:08

1

這裏是一個XSLT樣式表,你想要做什麼(保存在test.xsl):

<?xml version='1.0'?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       version="1.0"> 

<xsl:output method="text"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="testable"> 
    <xsl:value-of select='trigger'/><xsl:text>|</xsl:text> 
    <xsl:value-of select='message'/><xsl:text>|</xsl:text> 
    <xsl:value-of select='sales-info/san-a'/><xsl:text>|</xsl:text> 
    <xsl:value-of select='sales-info/san-b'/><xsl:text>|</xsl:text> 
    <xsl:value-of select='sales-info/san-c'/><xsl:text>&#xA;</xsl:text> 
</xsl:template> 

</xsl:stylesheet> 

命令(在這裏我假設你已經安裝了libxml2和的libxslt; xsltproc是一個命令行工具,使用這些庫):

xsltproc -o sample.txt test.xsl test.xml 

樣品的內容。TXT:

Trigger1|2012-06-14T00:03.54|no|no|no 
Trigger2|2012-06-15T00:03.54|yes|yes|no 
+0

x mlstarlet沒有安裝在我的服務器..是否有可能沒有xmlstarlet? – 2012-07-26 09:18:52

+0

是的,這是可能的。 – mzjn 2012-07-26 10:04:17

1

這裏是一個純bash的解決方案:

egrep '<trigger>|<message>|<san-.>' test.xml | sed -e 's/<[^>]*>//g' | while read line; do [ $((++i % 5)) -ne 0 ] && echo -n "$line|" || echo $line ; done 

但是,它只能在格式化爲您的樣品(在一個單獨的行中的每個元素)在文件中,它甚至沒有密切靈活/可靠的其他答案涉及正確的XML解析/轉換。

它可以增強,雖然在一定程度上...

+0

不錯,謝謝 – 2014-03-21 05:42:32