My xml is:
<record>
<field name="f1"/>
<id name="f2"/>
<id name="f3"/>
<field 开发者_如何学JAVAname="f4"/>
<info/>
</record>
I want to loop through it in xquery like this:
for $i in $records/record/field | $records/record/id
return
if ( .... $i is id .... ) then .... do something .... else ... do something else ...
Is this possible? How can distinguish when $i
is id and when it is field?
Another neat XQuery solution is to use typeswitch:
for $i in $records/record/field | $records/record/id
return
typeswitch($i)
case element(id) return ...
case element(field) return ...
default return ...
Instead of those attempts with name() or local-name() I would use self::id e.g.
if ($i[self::id]) then ... else ...
Check out the local-name
XQuery function - see the MSDN docs here.
Given a node or a node set, it should give you the node's name - the name of the tag. I guess that's what you're looking for, right??
E.g. if you do this:
DECLARE @input XML = '<record>
<field name="f1"/>
<id name="f2"/>
<id name="f3"/>
<field name="f4"/>
<info/>
</record>'
SELECT
inp.nod.query('local-name(.)')
FROM
@input.nodes('//*') AS inp(nod)
You get an output like this:
record
field
id
id
field
info
You can use a function library or create your own user defined function. Something like this:
for $i in $records/record/field | $records/record/id
return
if (name($i)="id") then .... do something .... else ... do something else ...
http://www.xqueryfunctions.com/xq/fn_name.html
How about something simpler and more XQuery-like
for $i in $records/record/field return do something with field,
for $i in $records/record/id return do something with id
In this case, the values returned by the first for will be merged with the values from the 2nd for.
Use typeswitch:
let $record :=
<record>
<field name="f1"/>
<id name="f2"/>
<id name="f3"/>
<field name="f4"/>
<info/>
</record>
for $e in $record/*
return
typeswitch ($e)
case element(id) return concat("id",$e/@name)
case element (field) return concat("field",$e/@name)
default return "other"
精彩评论