![](/img/trans.png)
[英]How to select multiple nodes based on a maximum child element value in XPath 1.0 (C#, WPF)
[英]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,则还可以拥有一个样式表文件,如下所示:
<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="'	'"/>
<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, '-')) >= $version-after-hyphen]"/>
</xsl:template>
<xsl:template match="change">
<xsl:apply-templates/>
<!-- Insert a newline after every <change> element -->
<xsl:text> </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.