Basex Xquery filter retrieved data - basex

<a id="aId" deleted="false">
<b id="bIdOne" deleted="false">
<c>cValue</c>
<d id="dId" deleted="true">
<e>eValue</e>
</d>
<f id="fId" deleted="false">
<g>gValue</g>
</f>
</b>
<b id="bIdTwo" deleted="true">
<c>cValue</c>
<d id="dId" deleted="true">
<e>eValue</e>
</d>
<f id="fId" deleted="false">
<g>gValue</g>
</f>
</b>
<b id="bIdThree" deleted="false">
<c>cValue</c>
<d id="dId" deleted="true">
<e>eValue</e>
</d>
<f id="fId" deleted="true">
<g>gValue</g>
</f>
</b>
<Y><yValue</Y>
</a>
Expected Output :
retrieve list of b and its child where deleted attribute is false, Expected output is below
query should be something like :
for $x in $data//descendant::[(#deleted=\"false\" or empty(#deleted))] return $x/b";
<b id="bIdOne" deleted="false">
<c>cValue</c>
<f id="fId" deleted="false">
<g>gValue</g>
</f>
</b>
<b id="bIdThree" deleted="false">
<c>cValue</c>
<Y><yValue</Y>
</b>

You are probably looking for something like this:
let $data := [your code above, fixed - your <Y> is in the wrong place for your output]
return
element root
{
for $e1 in $data//b[#deleted="false"]
let $dat :=$e1//*[not(#deleted="true")][not(ancestor::*[#deleted="true"])]
return
element{name($e1)}{$e1/#*,$dat}
}
Output should be your desired output.

Related

Exclude a grandchild from XML using XPath

Trying to exclude a specific grandchild when reading an XML structure using SQL Server 2017.
I have an example structure as follows:
<root>
<a id="parent">
<b id = "child1">
<c id = "grandchild1"/>
<c id = "grandchild2"/>
</b>
<b id = "child2">
<c id = "grandchild3"/>
<c id = "grandchild4"/>
</b>
</a>
</root>
I can exclude a specific child using c[not(contains(#id,"grandchild3"))] when I navigate to for example the node <b id = "child2">.
But how would I exclude that specific grandchild when processing the rest of the XML from the root node?
What i would like to receive, so I can write it to a file, is a structure like this:
<root>
<a id="parent">
<b id = "child1">
<c id = "grandchild1"/>
<c id = "grandchild2"/>
</b>
<b id = "child2">
<c id = "grandchild4"/>
</b>
</a>
</root>
As can be seen grandchild3 is now missing from this structure.
Doing this in a SELECT is surprisingly involved, but fortunately you don't need that. You can make a copy of your xml, modify it with .modify, then use that:
declare #original xml = '<root>
<a id="parent">
<b id = "child1">
<c id = "grandchild1"/>
<c id = "grandchild2"/>
</b>
<b id = "child2">
<c id = "grandchild3"/>
<c id = "grandchild4"/>
</b>
</a>
</root>'
declare #new xml = #original
set #new.modify('delete //c[#id="grandchild3"]')
select #new
gives
<root>
<a id="parent">
<b id="child1">
<c id="grandchild1" />
<c id="grandchild2" />
</b>
<b id="child2">
<c id="grandchild4" />
</b>
</a>
</root>
as desired.
The xpath //c[#id="grandchild3"] means "Any c node (anywhere in the document) with an id attribute with value grandchild3".

xidel: add object into json array

I want extract some information on a website. For this, i use xidel.
I use this command line:
xidel --template-file template.xml --dot-notation=on
and here my template file :
<actions>
<action>
... code before ...
<page url={$url}/>
<pattern>
<div class="row p-r-15 p-l-15 contenu-collec">
{$collection := []}
<t:loop>
{$manga := {}}
<div univers="1">
<div class="post-block collec-titre">
<h2 class="post-title detail-objets">{$manga.title:=.}</h2>
<div>
<input>{$manga.value:=#value}</input>
</div>
</div>
</div>
<!--<call action="test"/>-->
{$collection := $collection.push($manga)}
</t:loop>
</div>
</pattern>
<loop var="t" list="$collection">
<call action="test"/>
</loop>
</action>
<action id="test">
<page url="http://site">
<post name="editions" value="{$t.value}"/>
<post name="action" value="collec_objets_serie"/>
<post name="univers" value="1"/>
<post name="user_id" value="{$userid}"/>
<template>
<!-- <div style="display:block;">{$t.test}</div> -->
<t:loop>
{$t.tome := {}}
<a>{t.tome.url:=#href}</a>
</t:loop>
</template>
</page>
</action>
In the loop i create a object $manga. How to add this object to the $collection array ?
I have tried
{$collection := $collection.push($manga)}
but don't work.

T-SQL Find node with matching text and extract value from sibling node in XML field

I've a table with an xml field having content like this:
<ContentBlock xmlns="http://corp.com/wdpr/ContentBlock">
<key xlink:href="tcm:0-133036" xlink:title="entityCard" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<template xlink:href="tcm:0-132970" xlink:title="card-header-read-more-all-media" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<section>
<name xlink:href="tcm:0-132988" xlink:title="header" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Make a Friend</p>
</content>
</section>
<section>
<name xlink:href="tcm:0-133110" xlink:title="readMore" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Meet and greet friendly animals at the only petting zoo in Disney’s Animal
Kingdom park.
</p>
</content>
</section>
<section>
<name xlink:href="tcm:0-132939" xlink:title="readAll" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Meet and greet friendly animals.
</p>
<p xmlns="http://www.w3.org/1999/xhtml">Pet, brush and feed domesticated creatures
</p>
<ul xmlns="http://www.w3.org/1999/xhtml">
<li xmlns="http://www.w3.org/1999/xhtml">Goats</li>
</ul>
<p xmlns="http://www.w3.org/1999/xhtml">Handy animal brushes are available .
</p>
<p xmlns="http://www.w3.org/1999/xhtml">
<strong xmlns="http://www.w3.org/1999/xhtml">Keeping Clean</strong>
<br xmlns="http://www.w3.org/1999/xhtml"/>Guests are encouraged to cleanse.</p>
</content>
</section>
<media>
<name xlink:href="tcm:0-201994" xlink:title="media" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<key xlink:href="tcm:0-132952" xlink:title="170 x 96" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<image xlink:href="tcm:0-231377" xlink:title="section-01.jpg" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
</media>
</ContentBlock>
My goal is to have a query where I can find (for example) the <p> that contains the text "Make a Friend", then get the xlink:href of the <name> element in the same <section> tag.
I tried a few options like in this posts: here and here but I'm not getting the results I need.
This doesn't work
SELECT a.value1,
x.XmlCol.value('(section/content/p)[1]','VARCHAR(100)') AS SendMethod
FROM #test a
CROSS APPLY a.AppConfig.nodes('/ContentBlock') x(XmlCol)
WHERE x.XmlCol.exist('section/content/p[contains(.,"Make a Friend")]') = 1
How can I get it?
Thanks in advance. Guillermo.
Try it like this:
DECLARE #mockup TABLE(ID INT IDENTITY,YourXML XML);
INSERT INTO #mockup VALUES
('<ContentBlock xmlns="http://corp.com/wdpr/ContentBlock">
<key xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-133036" xlink:title="entityCard" xlink:type="simple" />
<template xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-132970" xlink:title="card-header-read-more-all-media" xlink:type="simple" />
<section>
<name xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-132988" xlink:title="header" xlink:type="simple" />
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Make a Friend</p>
</content>
</section>
<section>
<name xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-133110" xlink:title="readMore" xlink:type="simple" />
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Meet and greet friendly animals at the only petting zoo in Disney’s Animal
Kingdom park.
</p>
</content>
</section>
<section>
<name xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-132939" xlink:title="readAll" xlink:type="simple" />
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Meet and greet friendly animals.
</p>
<p xmlns="http://www.w3.org/1999/xhtml">Pet, brush and feed domesticated creatures
</p>
<ul xmlns="http://www.w3.org/1999/xhtml">
<li xmlns="http://www.w3.org/1999/xhtml">Goats</li>
</ul>
<p xmlns="http://www.w3.org/1999/xhtml">Handy animal brushes are available .
</p>
<p xmlns="http://www.w3.org/1999/xhtml">
<strong xmlns="http://www.w3.org/1999/xhtml">Keeping Clean</strong>
<br xmlns="http://www.w3.org/1999/xhtml" />Guests are encouraged to cleanse.</p>
</content>
</section>
<media>
<name xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-201994" xlink:title="media" xlink:type="simple" />
<key xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-132952" xlink:title="170 x 96" xlink:type="simple" />
<image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="tcm:0-231377" xlink:title="section-01.jpg" xlink:type="simple" />
</media>
</ContentBlock>');
-First I declare a variable to make the search-string dynamic:
DECLARE #SearchFor VARCHAR(100)='Make a Friend';
--Your XML has a default namespace in the outermost element.
--What makes things a bit weird: There is another default namespace on the element <p>
--We can declare this with a speaking prefix
WITH XMLNAMESPACES(DEFAULT 'http://corp.com/wdpr/ContentBlock'
,'http://www.w3.org/1999/xlink' AS xlink
,'http://www.w3.org/1999/xhtml' AS InnerDflt )
SELECT YourXML.value('(/ContentBlock/section[(content/InnerDflt:p/text())[1]=sql:variable("#SearchFor")]/name/#xlink:href)[1]','nvarchar(max)')
FROM #mockup
The query runs as this:
Start with <ContentBlock>. Look for a <section>, where the text() of <p> below <content> is the search-string. Important: At this stage we are still on the level of <section>. So we can continue the XPath with <name> and find the attribute there.
Shnugo stole my thunder but I'm still posting what I put together as it will work as well and demonstrates a few tricks (e.g. *: for when you're too lazy to add the correct namespace syntax) ;). I was going to mention the use of sql:variable to pass a SQL variable into your XPath expressions - shnugo's post demonstrates how to do that (it's missing in what I'm posting).
-- bonus sample data
DECLARE #xml XML =
'<ContentBlock xmlns="http://corp.com/wdpr/ContentBlock">
<key xlink:href="tcm:0-133036" xlink:title="entityCard" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<template xlink:href="tcm:0-132970" xlink:title="card-header-read-more-all-media" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<section>
<name xlink:href="tcm:0-132988" xlink:title="header" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Make a Friend</p>
</content>
</section>
<section>
<name xlink:href="tcm:0-133110" xlink:title="readMore" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Meet and greet friendly animals at the only petting zoo in Disney’s Animal
Kingdom park.
</p>
</content>
</section>
<section>
<name xlink:href="tcm:0-132939" xlink:title="readAll" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<content>
<p xmlns="http://www.w3.org/1999/xhtml">Meet and greet friendly animals.</p>
<p xmlns="http://www.w3.org/1999/xhtml">Pet, brush and feed domesticated creatures
</p>
<ul xmlns="http://www.w3.org/1999/xhtml">
<li xmlns="http://www.w3.org/1999/xhtml">Goats</li>
</ul>
<p xmlns="http://www.w3.org/1999/xhtml">Handy animal brushes are available .
</p>
<p xmlns="http://www.w3.org/1999/xhtml">
<strong xmlns="http://www.w3.org/1999/xhtml">Keeping Clean</strong>
<br xmlns="http://www.w3.org/1999/xhtml"/>Guests are encouraged to cleanse.</p>
</content>
</section>
<media>
<name xlink:href="tcm:0-201994" xlink:title="media" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<key xlink:href="tcm:0-132952" xlink:title="170 x 96" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
<image xlink:href="tcm:0-231377" xlink:title="section-01.jpg" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"/>
</media>
</ContentBlock>';
DECLARE #test TABLE (someId INT IDENTITY, AppConfig XML);
INSERT #test (AppConfig) VALUES (#xml),(CAST(REPLACE(REPLACE(CAST(#xml AS VARCHAR(8000)),
'Make a Friend','xxx'),'Keeping Clean','Make a Friend') AS XML));
-- SOLUTION
WITH XMLNAMESPACES ('http://www.w3.org/1999/xlink' AS xlink)
SELECT t.someId, href = cb.x.value('(../*:name/#xlink:href)[1]', 'varchar(8000)')
FROM #test AS t
CROSS APPLY t.AppConfig.nodes('*:ContentBlock/*:section/*:content') AS cb(x)
WHERE cb.x.exist('*:p[contains(.,"Make a Friend")]') = 1;
Returns:
someId href
----------- -------------
1 tcm:0-132988
2 tcm:0-132939

Get values from BuildLog on UI or Text from UI

Can anyone help me, to get the values from UI, which is a log, so they would not have static web elements,
I would like to get the values '0' and '800' and Differnce values, from log, by looking at the text 'CIA_StartTansportCost'
<div id="node_13646" class="leaf ch_13642 ch_13596 ch_13245">
<div id="msg_13646" class="msg l4">
<u id="ts_13646" class="ts">
<u class="ts_in">[12:48:59]</u>
</u>
<i class="mark error_msg actual status_err">
<i class="parent">[CIA_StartTransportCost] </i>
800
</i>
</div>
</div>
<div id="node_13647" class="leaf ch_13642 ch_13596 ch_13245">
<div id="msg_13647" class="msg l4">
<u id="ts_13647" class="ts">
<u class="ts_in">[12:48:59]</u>
</u>
<i class="mark error_msg stdout multiline ">
<i class="parent">[CIA_StartTransportCost] </i>
[Test Output] Running: "CIA_StartTransportCost", Expected Result: 0, Actual Result: 800, Difference: 80000.000000%, Test Threshold : 0.99, Test Result : FAIL, ExecutionSuccess : True RowsAffected: 1
</i>
</div>
</div>

SQL XML Insert multiple elements

Please help! I have a field of xml within a database. I am trying to insert a new element for each element in the field. E.g:
<some-element>
<a> </a>
<b> </b>
</some-element>
<some-element>
<a> </a>
<b> </b>
</some-element>
would insert element c and go to:
<some-element>
<a> </a>
<b> </b>
<c> </c>
</some-element>
<some-element>
<a> </a>
<b> </b>
<c> </c>
</some-element>
I know I can use #fieldname.modify('insert #CElement into (/some-element)[1]') but this only changes the first element! I want to repeat this for all elements.
Any help would be very much appreciated! (I am using SQL server 2008)
Moved from answer:
Thank you for your reply! Perhaps it would help if I was more specific... I am describing a simple table of data within the xml. I am trying to add a new column. I can add the column within the column descriptions but I need to add the column element to all the rows. (It would not be a simple task to change the structure and I would like to avoid this!) E.g:
<Table>
<Columns>
<Column ID="0">
<Column-Name>0NAME</Column-Name>
</Column>
<Column ID="1">
<Column-Name>1NAME</Column-Name>
</Column>
<Column ID="2">
<Column-Name>2NAME</Column-Name>
</Column>
<Column ID="3">
<Column-Name>!!!! THIS COLUMN IS BEING ADDED !!!!!</Column-Name>
</Column>
</Columns>
<Rows>
<Row ID="0">
<C ID="0">0 contents here</C>
<C ID="1">0 contents here</C>
<C ID="2">0 contents here</C>
<!-- NEW COLUMN NEEDS TO BE CREATED HERE -->
</Row>
<Row ID="1">
<C ID="0">1 contents here</C>
<C ID="1">1 contents here</C>
<C ID="2">1 contents here</C>
<!-- NEW COLUMN NEEDS TO BE CREATED HERE -->
</Row>
<Row ID="2">
<C ID="0">2 contents here</C>
<C ID="1">2 contents here</C>
<C ID="2">2 contents here</C>
<!-- NEW COLUMN NEEDS TO BE CREATED HERE -->
</Row>
</Rows>
</Table>
You can recreate your XML, e.g.:
declare #x xml = '<some-element>
<a>1</a>
<b>2</b>
</some-element>
<some-element>
<a>3</a>
<b>4</b>
</some-element>'
select #x.query
('
for $e in some-element
return
<some-element>
{ $e/a }
{ $e/b }
<c/>
</some-element>
')
Adapting the answer provided by Kirill Polishchuk to the new XML structure:
select #XML.query
('
for $c in Table/Columns
return
<Table>
<Columns>
{ $c/* }
</Columns>
<Rows>
{
for $r in Table/Rows/Row
return
<Row>
{ $r/* }
<C ID="3"/>
</Row>
}
</Rows>
</Table>
')

Resources