Bash
如何表示 XPath 函式以輸出每個輸入元素?
我正在使用這個命令:
xmllint --xpath 'substring-after(string(//item/link), "_")' rss.xml
並獲得所需的輸出,除了它在第一個元素上。我將如何解決此問題以將其應用於每個
link
?我願意使用任何實用程序,只要接受範例輸入並且可以使用一個表達式來獲得所需的輸出。
樣本輸入:
<rss version="2.0"> <channel> <title>Malicious IPs | By Last Bad Event | Project Honey Pot</title> <link><![CDATA[http://www.projecthoneypot.org/list_of_ips.php]]></link> <description/> <copyright>Copyright 2021 Unspam Technologies, Inc</copyright> <language>en-us</language> <lastBuildDate>July 03 2021 07:15:12 PM</lastBuildDate> <image> <url>http://www.projecthoneypot.org/images/small_phpot_logo.jpg</url> <title>Project Honey Pot | Distribute Spammer Tracking System</title> <link>http://www.projecthoneypot.org</link> </image> <item> <title>92.204.241.167 | C</title> <link>http://www.projecthoneypot.org/ip_92.204.241.167</link> <description>Event: Bad Event | Total: 3,061 | First: 2021-03-27 | Last: 2021-07-03</description> <pubDate>July 03 2021 07:15:12 PM</pubDate> </item> <item> <title>181.24.239.244</title> <link>http://www.projecthoneypot.org/ip_181.24.239.244</link> <description>Event: Bad Event | Total: 1 | First: 2021-07-03 | Last: 2021-07-03</description> <pubDate>July 03 2021 07:15:12 PM</pubDate> </item> <item> <title>193.243.195.66 | S</title> <link>http://www.projecthoneypot.org/ip_193.243.195.66</link> <description>Event: Bad Event | Total: 4 | First: 2021-06-12 | Last: 2021-07-03</description> <pubDate>July 03 2021 07:15:12 PM</pubDate> </item> </channel> </rss>
期望的輸出:
92.204.241.167 181.24.239.244 193.243.195.66
目前輸出:
92.204.241.167
您實際上無法單獨使用 XPath 1.0 來實現這一點。您不能返回字元串序列,因為 XPath 1.0 中沒有這種數據類型,並且您不能返回連接各種子字元串的單個字元串,因為您仍然需要子字元串序列作為中間結果,並且同樣,沒有這樣的數據類型。因此,您要麼需要遷移到 XPath 2.0+,要麼需要執行多個 XPath 表達式的宿主語言的一些幫助——這就是 @Kusalananda 的 xmlstarlet 解決方案正在做的事情。
但是,您使用的是命令行,因此有很多可用的工具可供選擇——您可以像使用 XPath 一樣輕鬆地使用 XQuery,而且您當然不限於古老的 XPath 1.0 版本。例如,你可以用撒克遜人做
java net.sf.saxon.Query -qs:"//item/link!substring-after(., '_')" -s:rss.xml
這使用 XPath 3.0 和 XQuery 3.0 中可用的“bang”運算符,它將右側的表達式應用於左側表達式選擇的每個項目。
使用
xmlstarlet
:xmlstarlet sel -t -m '//item/link' -v 'substring-after(., "_")' -nl rss.xml
這首先匹配 (
-m
) 所有//item/link
節點,然後獲取-v
與匹配節點值中第一個下劃線字元之後的字元串關聯的值 ( )。最後-nl
在每個結果字元串之間輸出一個換行符。第二個表達式 (
substring-after()
) 將針對與第一個匹配的集合中的每個節點進行評估。