简体   繁体   English

xpath-如何基于值选择多个节点

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

I have some xml and I would like to dynamically extract some information, based on some incoming data. 我有一些xml,我想根据一些传入数据动态提取一些信息。

Here is some 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>

And I'd like to pass in the string '0-2' and find out all versions since 0-2 like this: 我想传入字符串“ 0-2”并找出 0-2 以来的所有版本如下所示:

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

It's complicated by the fact that the numbers I'm comparing start with '0-'. 我要比较的数字以“ 0-”开头的事实使情况变得复杂。

However luckily you can remove the '0-' and get a real number, which corresponds to a position, so I've got as far as something like this: 但是幸运的是,您可以删除'0-'并获得一个与位置相对应的实数,因此,我得到了如下信息:

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

which just concatenates all the descriptions and spits them out. 只是将所有描述串联起来,然后将它们吐出来。

How do I loop through them and select multiple node content? 如何遍历它们并选择多个节点内容?

Looks like you already found a solution, but just to offer an alternative: if you don't mind using XSLT, you could also have an stylesheet file like this: 看起来您已经找到了解决方案,但仅是提供一种替代方法:如果您不介意使用XSLT,则还可以拥有一个样式表文件,如下所示:

stylesheet.xsl 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>

You could then run it with xsltproc eg like this: 然后可以使用xsltproc运行它,例如:

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

And the output would be: 输出将是:

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

I'm fairly certain it'll be faster than executing xmllint multiple times and perhaps somewhat easier to maintain in the long run as well. 我相当确定,它将比多次执行xmllint更快,并且从长远来看,也许也更容易维护。 libxml2 (which you already have installed since you have xmllint ) includes xsltproc , too, so that shouldn't be a problem, either. libxml2 (由于具有xmllint安装),也包含xsltproc ,因此也不是问题。

Ok so I got it working like this: 好的,所以我可以这样工作:

#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

Output looks like this: 输出看起来像这样:

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

It's much slower than when I was using grep and tr, but it does allow me to parse the date correctly and it looks exactly as I wanted. 它比我使用grep和tr时要慢得多,但是它确实允许我正确解析日期,并且看起来完全符合我的要求。

Success! 成功!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM