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
/codein
has value of of values have in array - this node
codeout
can namedcodeout
orcodein
, 1 of these - the date on
timeperiod
must 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