각 입력 요소를 출력하는 XPath 함수를 표현하는 방법은 무엇입니까?

각 입력 요소를 출력하는 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

답변1

사용 xmlstarlet:

xmlstarlet sel -t -m '//item/link' -v 'substring-after(., "_")' -nl rss.xml

이는 먼저 -m모든 //item/link노드와 일치( )한 다음 -v일치된 노드 값( )에서 첫 번째 밑줄 문자 다음에 오는 문자열과 연결된 값을 가져옵니다. 마지막으로 -nl각 결과 문자열 사이에 개행 문자를 출력합니다.

substring-after()두 번째 표현식( )은 첫 번째 표현식과 일치하는 컬렉션의 각 노드에 대해 평가됩니다.

답변2

실제로 XPath 1.0만으로는 불가능합니다. XPath 1.0에는 그러한 데이터 유형이 없기 때문에 일련의 문자열을 반환할 수 없으며 중간 결과로 일련의 하위 문자열이 여전히 필요하고 다시 말하지만 그러한 유형이 없기 때문에 개별 하위 문자열을 연결하는 단일 문자열을 반환할 수 없습니다. 데이터. 따라서 XPath 2.0 이상으로 마이그레이션해야 하거나 여러 XPath 표현을 수행하는 호스트 언어의 도움이 필요합니다. 이것이 @Kusalananda의 xmlstarlet 솔루션이 수행하는 작업입니다.

그러나 명령줄을 사용하므로 선택할 수 있는 도구가 매우 다양합니다. XPath를 사용하는 것처럼 쉽게 XQuery를 사용할 수 있으며 확실히 고대 XPath 1.0 버전에 국한되지 않습니다. 예를 들어 Saxon의 경우 다음을 수행할 수 있습니다.

java net.sf.saxon.Query -qs:"//item/link!substring-after(., '_')" -s:rss.xml

이는 XPath 3.0 및 XQuery 3.0에서 사용할 수 있는 "뱅" 연산자를 사용합니다. 이 연산자는 왼쪽 표현식에 의해 선택된 각 항목에 오른쪽 표현식을 적용합니다.

답변3

내 거히델최신 XPath 표현식을 실행하기 위한 또 다른 도구입니다.

xidel rss.xml --xpath "//item/link/substring-after(., '_')"

관련 정보