簡體   English   中英

xpath-如何基於值選擇多個節點

[英]xpath - how to select multiple nodes based on value

我有一些xml,我想根據一些傳入數據動態提取一些信息。

這是一些xml:

<?xml version="1.0" encoding="UTF-8"?>
<releaseNote>
 <name>DECOUPLING_client</name>
  <change>
   <date hour="12" day="24" second="44" year="2012" month="10" minute="46"/>
   <submitter>Automatically Generated</submitter>
   <description>ReleaseNote Created</description>
  </change>
  <change>
   <version>0-2</version>
   <date hour="12" day="24" second="48" year="2012" month="11" minute="46"/>
   <submitter>fred.darwin</submitter>
   <description> first iteration of decoupling client - copied files from old decoupling module</description>
   <install/>
  </change>
 <change>
  <version>0-3</version>
  <date hour="16" day="25" second="34" year="2012" month="11" minute="52"/>
  <submitter>fred.darwin</submitter>
  <description> promoting changes</description>
  <install/>
 </change>
</releaseNote>

我想傳入字符串“ 0-2”並找出 0-2 以來的所有版本如下所示:

0-3     fred.darwin       25/11/2012      promoting changes

我要比較的數字以“ 0-”開頭的事實使情況變得復雜。

但是幸運的是,您可以刪除'0-'並獲得一個與位置相對應的實數,因此,我得到了如下信息:

xmllint --xpath '/releaseNote/change[position()>2]/description/text() ${file}

只是將所有描述串聯起來,然后將它們吐出來。

如何遍歷它們並選擇多個節點內容?

看起來您已經找到了解決方案,但僅是提供一種替代方法:如果您不介意使用XSLT,則還可以擁有一個樣式表文件,如下所示:

stylesheet.xsl

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" version="1.0" encoding="utf-8"/>

  <xsl:param name="version"/>

  <!-- Strip white-space-only text nodes in all elements -->
  <xsl:strip-space elements="*"/>

  <xsl:variable name="version-after-hyphen" select="number(substring-after($version, '-'))"/>

  <!-- XML entity for a tab -->
  <xsl:variable name="DELIMITER" select="'&#9;'"/>

  <xsl:template match="/">
    <!--
    Apply every <change> element with a <version> child whose value is $version
    or greater.
    -->
    <xsl:apply-templates
      select="releaseNote/change[number(substring-after(version, '-')) &gt;= $version-after-hyphen]"/>
  </xsl:template>

  <xsl:template match="change">
    <xsl:apply-templates/>
    <!-- Insert a newline after every <change> element -->
    <xsl:text>&#10;</xsl:text>
  </xsl:template>

  <xsl:template match="submitter | description">
    <xsl:value-of select="concat($DELIMITER, normalize-space(.))"/>
  </xsl:template>

  <xsl:template match="version">
    <xsl:value-of select="."/>
  </xsl:template>

  <xsl:template match="date">
    <!-- Format date -->
    <xsl:value-of select="concat($DELIMITER, @day, '/', @month, '/', @year, ' ', @hour, ':', @minute)"/>
  </xsl:template>
</xsl:stylesheet>

然后可以使用xsltproc運行它,例如:

xsltproc --stringparam version 0-2 stylesheet.xsl releaseNote.xml

輸出將是:

0-2 24/11/2012 12:46  fred.darwin first iteration of decoupling client - copied files from old decoupling module
0-3 25/11/2012 16:52  fred.darwin promoting changes

我相當確定,它將比多次執行xmllint更快,並且從長遠來看,也許也更容易維護。 libxml2 (由於具有xmllint安裝),也包含xsltproc ,因此也不是問題。

好的,所以我可以這樣工作:

#first count number of nodes ie how many changes (could be eg 979)
numChanges=`xmllint --xpath 'count(/releaseNote/change)' ${MPATH}/${mod}/resources/ReleaseNote.xml`
echo "found $numChanges changes"
#even though last one shows as 0-952
lastModule=`xmllint --xpath '/releaseNote/change[last()]/version/text()' ${MPATH}/${mod}/resources/ReleaseNote.xml`
#so

#then loop through from our one to the end
#use a unix loop
echo "version number ${versionNumber} num changes ${numChanges}"
#for i in {${versionNumber}..${numChanges}}; do
i=$versionNumber
while [[ $i -le $numChanges ]]  ; do
#and for each item in the list spit out description, version, submitter and try to parse date
xmllint --xpath "/releaseNote/change[$i]/version/text()" ${MPATH}/${mod}/resources/ReleaseNote.xml
echo -en ' \t '
xmllint --xpath "string(/releaseNote/change[$i]/date/@day)" ${MPATH}/${mod}/resources/ReleaseNote.xml
echo -en '/'
xmllint --xpath "string(/releaseNote/change[$i]/date/@month)" ${MPATH}/${mod}/resources/ReleaseNote.xml
echo -en '/'
xmllint --xpath "string(/releaseNote/change[$i]/date/@year)" ${MPATH}/${mod}/resources/ReleaseNote.xml
echo -en ' '
xmllint --xpath "string(/releaseNote/change[$i]/date/@hour)" ${MPATH}/${mod}/resources/ReleaseNote.xml
echo -en ':'
xmllint --xpath "string(/releaseNote/change[$i]/date/@minute)" ${MPATH}/${mod}/resources/ReleaseNote.xml
echo -en ' \t '
xmllint --xpath "/releaseNote/change[$i]/submitter/text()" ${MPATH}/${mod}/resources/ReleaseNote.xml
echo -en ' \t '
xmllint --xpath "/releaseNote/change[$i]/description/text()" ${MPATH}/${mod}/resources/ReleaseNote.xml
((i = i + 1))
echo
done

輸出看起來像這樣:

0-96     21/4/2014 17:56     onkar.sharma     test case for subscription validation
0-97     28/5/2014 15:58     trushant.patel       JIRAET81
0-98     9/6/2014 18:10      vivek.mittal     Refinement for GetFindPackagesWithService flow

它比我使用grep和tr時要慢得多,但是它確實允許我正確解析日期,並且看起來完全符合我的要求。

成功!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM