c# - XPath to select the nodes that matches -
i have xml looks this:
<?xml version="1.0"?> <rootname> <randomnode v="somevalue"/> <series> <idendity v="c16"/> <codeout v="c41073"/> <period> <timeperiod v="2013-07-18t22:00z/2013-07-19t22:00z"/> <resolution v="pt60m"/> <interval> <pos v="1"/> <qty v="14.1"/> </interval> <interval> <pos v="2"/> <qty v="20.7"/> </interval> and need xpath returns period nodes matches these conditions:
- the node
codeout/codeinhas value of of values have in array - this node
codeoutcan namedcodeoutorcodein, 1 of these - the date on
timeperiodmust match
the node repeates on xml series node. in other words, there 1 period per series, there lot of different series.
for example, period nodes have codeout or codein value being c41073 or b85028 , date being 2013-07-18.
i tried, match multiple names, using like:
//*[@v="c41073"] | //*[@v="b85028"] | ... but think better if matches correct nodes, in case other node has same value, isn't it?
i searching use "contains", works in different way.
i'm using .net, if matters, , i'm going use xpath on .selectnodes() function.
edit:
something strange happening. maybe syntax not correct. @ tests:
this: doc.selectnodes("/*")(0).name returning rootname
this: doc.selectnodes("/*/*").count returning 912
this: doc.selectnodes("/*/*")(11).name returning series
but this: doc.selectnodes("/rootname").count returning 0
this: doc.selectnodes("/*/series").count returning 0
, this: doc.selectnodes("/*/rootname").count returning 0
making other xpath sequences suggested in answers not working.
edit:
ok, namespace, did this:
dim xmlnsmanager xml.xmlnamespacemanager = new system.xml.xmlnamespacemanager(doc.nametable) xmlnsmanager.addnamespace("ns", "http://example") and adding ns: before every element node name in xpath sequence. (see more information it: is possible specify namespace prefix once in xpath expression?)
to select of period elements limited codein/codeout list, this:
/rootname/series[(codeout/@v = 'c41073') or (codeout/@v = 'b85028') or (codein/@v = 'c41073') or (codein/@v = 'b85028')]/period if don't want list each item in list separate condition, concatenate them delimited list , use contains function, this:
/rootname/series[(codeout/@v , contains('|c41073|b85028|', concat('|', codeout/@v, '|'))) or (codein/@v , contains('|c41073|b85028|', concat('|', codein/@v, '|')))]/period notice, avoid problem substring c4 matching full value, c41073, need concatenate delimiter before , after attribute value. also, need make sure delimiter exists @ beginning , ending of delimited list of values. also, whatever delimiter choose must invalid character never occur in of values in list.
however, limiting timeperiod bit more problematic, since appears non-standard time range value. if start , end times stored in separate nodes, easier.
if need match exact timeperiod value, instance, this:
/rootname/series[(codeout/@v = 'c41073') or (codeout/@v = 'b85028') or (codein/@v = 'c41073') or (codein/@v = 'b85028')]/period[timeperiod/@v = '2013-07-18t22:00z/2013-07-19t22:00z'] you can split string on / character, substring-before(timeperiod, '/') , substring-after(timeperiod, '/'), unless using xpath 2.0, can't compare strings see if greater or less than. if using 2.0, compare each of substrings search value using compare function, it's still messy. it's best handle time-range comparison in .net code.
Comments
Post a Comment