I have the following xml:
<Root>
<Result img="1.png" name="a">
<Programs>
<Program name="foo1">
<ProgramID>1</ProgramID>
</Program>
</Programs>
</Result>
<Result img="2.png" name="b">
<Programs>
<Program name="foo1">
<ProgramID>1</ProgramID>
</Program>
<Program name="foo2">
<ProgramID>2</ProgramID>
</Program>
</Programs>
</Result>
<Result img="3.png" name="c">
<Programs>
<Program name="foo1">
<ProgramID>1</ProgramID>
</Program>
</Programs>
</Result>
<Result img="4.png" name="d">
<Programs>
<Program name="foo1">
<ProgramID>1</ProgramID>
</Program>
</Programs>
</Result>
</Root>
I am trying to filter xml by ProgramID with below linq statement but i always get no results back when i pass a value of 2, strangely when i pass a value of 1 in I do get expected results back which is all four results.
xOut = New XElement("Root", _
From s In x...<Result> _
Where s.<Programs>.<Program>.<ProgramID>.Value = 2 _
Select s)
What is wrong with linq query. Why does a 1 work but a 2 does not? I would also like xml structure preserved after filtering.
Here's how you'd do it in C#:
var xOut = new XElement(
"Root",
x.Descendants("Result")
.Where(y => y.Descendants("Programs").Descendants("Program").Descendants("ProgramID")
.Any(z => z.Value == "2")));
Not sure what the VB.NET equivalent would be though, sorry.
Related
Hej. I am new at XML-query and have some problem finding a way to combine the result of two xquery into one.
Consider the XML:
<programs>
<program id="488">
<editor>Anna</editor>
<channel>132</channel>
<category>5</category>
</program>
<program id="178">
<editor>Olle</editor>
<channel>132</channel>
<category>68</category>
</program>
<program id="179">
<editor>Olle</editor>
<channel>132</channel>
<category>10</category>
</program>
</programs>
I want to extract list of editors along with the categories they have worked on which would be like this:
<li>Anna 5 </li>
<li>Olle 68 10</li>
Here is the xquery code I am using
let $editors :=
for $d in $sr/sr/programs/program
where $d/channel = "132"
return $d/editor
let $cat :=
for $a in $sr/sr/programs/program
where $a/editor = data($editors)
return concat($a/editor ,' ', $a/category)
for $result in distinct-values($cat)
return <li>{string($result)}</li>
Appreciate all the helps!
I would iterate over the distinct list of editors, obtained from an XPath with a predicate to restrict to those with channel equal to 132, and then retrieve a distinct list of categories for those editors with a similar XPath with predicate filter, and then return the HTML with those values:
for $editor in distinct-values($sr/sr/programs/program[channel eq 132]/editor)
let $categories :=
distinct-values($sr/sr/programs/program[channel eq 132 and editor eq $editor]/category)
return <li>{$editor, $categories}</li>
The following XML sample shows data records of type 'Master', which are linked to 0..N contents of type 'Series'. I want to detect the number of existing Series records for Masters with the same title () attribute.
<?xml version="1.0" encoding="UTF-8"?>
<program_file fechaCreacion="20180919184224">
<version>1.0</version>
<programs>
<program id_programa="1">
<tipo_programa>Master</tipo_programa>
<titulo >tit1</titulo>
<año>2018</año>
</program>
<program id_programa="2">
<tipo_programa>Master</tipo_programa>
<titulo >tit1</titulo>
<año>2018</año>
</program>
<program id_programa="3">
<tipo_programa>Master</tipo_programa>
<titulo >tit2</titulo>
<año>2018</año>
</program>
<program id_programa="5">
<id_serie>1</id_serie>
<tipo_programa>Series</tipo_programa>
<episodio>8</episodio>
<temporada>1</temporada>
<titulo >tit1</titulo>
<año>2018</año>
</program>
<program id_programa="6">
<id_serie>2</id_serie>
<tipo_programa>Series</tipo_programa>
<episodio>8</episodio>
<temporada>1</temporada>
<titulo >tit1</titulo>
<año>2018</año>
</program>
<program id_programa="7">
<id_serie>3</id_serie>
<tipo_programa>Series</tipo_programa>
<episodio>8</episodio>
<temporada>1</temporada>
<titulo >tit2</titulo>
<año>2018</año>
</program>
</programs>
</program_file>
With this example what I expect to obtain, in a tabular format, is:
I managed to make a query that gives me the correct results (with BaseX) using Group by:
let $dup_masters := doc("C:/Users/fgarcia/Documents/Optiva/Orange/programs_sample.xml")/program_file/programs
return
<distinct-names> {
for $dups in $dup_masters/program
order by $dups/titulo
group by $title := $dups/titulo
return
if(count(distinct-values($dups[tipo_programa="Master"]/#id_programa)) > 1) then
element {"Master"}
{
attribute {"title"} {$title},
for $id in distinct-values($dups[tipo_programa="Master"]/#id_programa)
return (
<td>{$id}</td>,
<td>{count($dups[id_serie=($id)])}</td>
)
}
else ()
}</distinct-names>
The problem is that when I move this code to Exist-db I obtain no results, and I'm wondering if this can be related to the implementation of Group By in exist. Any ideas/hints on how to solve this in a different manner are welcome!
I want to insert a node using below code but if i will rerun the code i don't want my node to be repeated twice-
let $doc := fn:doc("abc.xml")
(: abc.xml looks like--
<root>
<value1>somevalue</value1>
<value2>somevalue</value2>
<value3>somevalue</value3>
<value4>somevalue</value4>
<value5>Australia</value5>
<value6>India</value6>
<value7>USA</value7>
<value8>somevalue</value8>
<value9>somevalue</value9>
<value10>somevalue</value10>
</root> :)
let $element := element Root{
element A{"A"},
element B{"B"},
element C{"C"},
element D{"D"},
element E{"E"}
}
let $doc := xdmp:node-insert-after(doc("abc.xml")//value4, $element)
return doc("abc.xml")
Whenever i am running this query my ELEMENT is getting inserted after value4 but i want that if i am running this multiple times then my element should get inserted only once and not multiple times.
Example- If i am running this 2 times-
Actual Output-
<root>
<value1>somevalue</value1>
<value2>somevalue</value2>
<value3>somevalue</value3>
<value4>somevalue</value4>
<Root>
<A>A</A>
<B>B</B>
<C>C</C>
<D>D</D>
<E>E</E>
</Root>
<Root>
<A>A</A>
<B>B</B>
<C>C</C>
<D>D</D>
<E>E</E>
</Root>
<value5>Australia</value5>
<value6>India</value6>
<value7>USA</value7>
<value8>somevalue</value8>
<value9>somevalue</value9>
<value10>somevalue</value10>
</root>
Expected Output-
<root>
<value1>somevalue</value1>
<value2>somevalue</value2>
<value3>somevalue</value3>
<value4>somevalue</value4>
<Root>
<A>A</A>
<B>B</B>
<C>C</C>
<D>D</D>
<E>E</E>
</Root>
<value5>Australia</value5>
<value6>India</value6>
<value7>USA</value7>
<value8>somevalue</value8>
<value9>somevalue</value9>
<value10>somevalue</value10>
</root>
Any Suggestions ??
Before inserting the node, check that it's not already there:
if (empty(child::Root)) then xdmp:update....
Note that you are using xdmp:node-insert-after -- this will do what the function name says (insert after) each time its called. As commented, you can conditionally call xdmp:node-update instead. Alternatively you can use xquery directly:
doc("file.xml" )/root ! <root>{ ./*[ . << ./value4] , $element , $a/value4, ./*[. >> ./value4] }</root>
Note: the "<<" operator compares "document order" (position not value)
i am in the middle of creating xquery replace-value of node action in XQuery.
But seems this code is not working therefore the IF-ELSE statement is always going to else.
This is my code:
declare function local:replacing($contextData as element())
as element()*
{
copy $pipeline := $contextData/Handler/Data/*
modify(
if(not(empty(data($pipeline/Payload/sample/transactionType)))) then
replace value of node $pipeline/Payload/sample/transactionType with 'XXX' else (),
if(not(empty(data($pipeline/Payload/sample/revision)))) then
replace value of node $pipeline/Payload/sample/revision with 'XXX' else ()
)
return $pipeline
};
I try against this sample XML but the result is always not XXX when the field revision is having value. (this always goes to else statement)
let $result :=
<root>
<Handler>
<Data>
<root>
<Payload>
<sample>
<transactionType></transactionType>
<revision>123</revision>
<board>1</board>
<mission>1</mission>
<method>Manual</method>
<listOfBoard>
<board>
<type>small</type>
<amount>5054</amount>
<token>300</token>
</board>
</listOfBoard>
<pricing>300</pricing>
<playing>Wed</playing>
</sample>
</Payload>
</root>
</Data>
</Handler>
</root>
Current Result:
<root>
<Payload>
<sample>
<transactionType/>
<revision>123</revision>
<board>1</board>
<mission>1</mission>
<method>Manual</method>
<listOfBoard>
<board>
<type>small</type>
<amount>5054</amount>
<token>300</token>
</board>
</listOfBoard>
<pricing>300</pricing>
<playing>Wed</playing>
</sample>
</Payload>
</root>
Expected Result
<root>
<Payload>
<sample>
<transactionType/>
<revision>XXX</revision>
<board>1</board>
<mission>1</mission>
<method>Manual</method>
<listOfBoard>
<board>
<type>small</type>
<amount>5054</amount>
<token>300</token>
</board>
</listOfBoard>
<pricing>300</pricing>
<playing>Wed</playing>
</sample>
</Payload>
</root>
Any ideas for this?
Update
As recommended by Har below, i change the code into:
if(not(empty(data($pipeline/Payload/sample/transactionType)))) then
replace value of node $pipeline/Payload/sample/transactionType with 'XXX'
else (
if(not(empty(data($pipeline/Payload/sample/revision)))) then
replace value of node $pipeline/Payload/sample/revision with 'XXX' else ()
)
But seems the result is the same. It still goes to else () statement.
Any ideas?
Thank you before.
The problem was, empty() checks for empty sequence, so sequence containing one empty string is considered true by empty(). You can just pass data() result to if since empty has Effective Boolean Value of false :
if(data($pipeline/Payload/sample/transactionType)) then
replace value of node $pipeline/Payload/sample/transactionType with 'XXX' else (),
if(data($pipeline/Payload/sample/revision)) then
replace value of node $pipeline/Payload/sample/revision with 'XXX' else ()
i'm getting the xmldata from the httpservice (using cgi) and i have not set resultformat(it is coming as an object only),the xml data in this format
<root>
<employee name="xxx" age="xx" gender="xxx"/>
<employee name="xxx" age="xx" gender="xxx"/>
<employee name="xxx" age="xx" gender="xxx"/>
</root>
when i was tried to count the employee tag,i getting the problem, my code will like this:
var i:int=o;
for each(var obj:object in event.result.root.employee)
{
i++;
}
i getting the count as 3 but the problem it give the count as 3 when the coming data i.e)the xml data is
<root>
<employee name="xxx" age="xx" gender="xxx"/>
<root>
actually i want to count the number of employees tag not all subtag ,
i hope you may save my time
Thanks in advance..
event.result.employee.length()
or look here for .ChildNodes
http://www.republicofcode.com/tutorials/flash/xml/
or another one
http://www.underground-flash.com/2008/02/arraylength-vs-xmllength-in-as3.html
and one more professional
http://www.thetechlabs.com/tutorials/xml/working-with-xml-e4x-and-actionscript-3/