Bash

如何表示 XPath 函式以輸出每個輸入元素?

  • July 21, 2021

我正在使用這個命令:

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()) 將針對與第一個匹配的集合中的每個節點進行評估。

引用自:https://unix.stackexchange.com/questions/656991