2015-06-11 285 views
1

您好我需要對這部分xml進行一些文本處理。 刪除一些標籤是沒有問題的。我之前需要將汽車ID重命名爲CAR_ID,並在TRIP標籤內移動。更改XML結構

ie:MLStarlet Toolkit?

xmlstarlet somevariable

原始

<car> 
    <id>155028827</id> 
    <trip> 
     <id>1</id> 
     <date>1.1.1970</date> 
    </trip> 
    <trip> 
     <id>2</id> 
     <date>1.1.1970</date> 
    </trip> 
    </car> 

厚望結果

<trip> 
    <car_id>155028827</id> 
    <id>1</id> 
    <date>1.1.1970</date> 
</trip> 
<trip> 
    <car_id>155028827</id> 
    <id>2</id> 
    <date>1.1.1970</date> 
</trip> 
+0

你已經嘗試過什麼,失敗的部分或未完成的行爲是什麼? – NeronLeVelu

回答

1

我想說

xmlstarlet ed -i '/car/trip/descendant::node()[1]' -t elem -n car_id -u '/car/trip/car_id' -x 'ancestor::node()["car"]/id/text()' filename.xml | xmlstarlet sel -t -c '/car/trip' 

這分爲兩個部分:

xmlstarlet ed \ 
    -i '/car/trip/descendant::node()[1]' -t elem -n car_id \ 
    -u '/car/trip/car_id' -x 'ancestor::node()["car"]/id/text()' \ 
    filename.xml 

xmlstarlet sel -t -c '/car/trip' 

第一種是xmlstarlet ed命令,這意味着XML進去,被編輯時,和編輯XML熄滅。該編輯是

-i '/car/trip/descendant::node()[1]' -t elem -n car_id 

這將插入每個/car/trip節點的第一傳人之前car_id,並

-u '/car/trip/car_id' -x 'ancestor::node()["car"]/id/text()' 

所有/car/trip/car_id節點的值設置爲文本id子節點的car祖先的內節點。僅此一點就產生

<?xml version="1.0"?> 
<car> 
    <id>155028827</id> 
    <trip> 
    <car_id>1550288271</car_id> 
    <id>1</id> 
    <date>1.1.1970</date> 
    </trip> 
    <trip> 
    <car_id>1550288272</car_id> 
    <id>2</id> 
    <date>1.1.1970</date> 
    </trip> 
</car> 

其然後通過

xmlstarlet sel -t -c '/car/trip' 

此選擇(和打印)該XML數據的/car/trip節點管道,產生

<trip> 
    <car_id>1550288271</car_id> 
    <id>1</id> 
    <date>1.1.1970</date> 
    </trip><trip> 
    <car_id>1550288272</car_id> 
    <id>2</id> 
    <date>1.1.1970</date> 
    </trip> 

你可以,如果格式化惹惱你,使用

xmlstarlet sel -t -c '/car/trip | /car/text()' 

保留標籤之間的空白(並獲得更易讀的格式化輸出);隨着這種變化,輸出是

<trip> 
    <car_id>1550288271</car_id> 
    <id>1</id> 
    <date>1.1.1970</date> 
    </trip> 
    <trip> 
    <car_id>1550288272</car_id> 
    <id>2</id> 
    <date>1.1.1970</date> 
    </trip> 

......在頂部有兩個空白行;它們是/car/id節點前後的換行符。不幸的是,輸出數據不再是有效的XML,所以我們不能通過一個XML漂亮的打印機(這是我真正想做的)來管理它。由於我懷疑它會嵌入到更多的XML中(因此它可以被正確解析),如果格式很重要,我的建議是首先將其嵌入,然後通過一個漂亮的打印機將整個XML傳遞給後者。

+0

你是最棒的。 thx很多,我不是程序員,「descendant :: node()[1]」聽起來像來自火星的音樂:)。非XML的標準是沒有問題的,我會準備插入到MySQL的XML。Thx再次。 –

+0

這些過濾器是[XPath](http://www.w3schools.com/xpath/)表達式; '後代'是[Xpath軸](http://www.w3schools.com/xpath/xpath_axes.asp)。處理XML時XPath是一個非常方便的工具(並且學習起來不是很困難),所以我鼓勵您閱讀它。 – Wintermute

+0

您可以使用'--root'或'-R'(如'xmlstarlet sel -R -t ...')將輸出包裝到單個節點中。 – npostavs