Transform XML with default values in Mulesoft - mule

Assuming I have XMLs like
<a>
<b>Some Value</b>
</a>
...or...
<a>
<b type=1 />
</a>
...or...
<a/>
and want to have some values and attributes defined in output like
<a>
<b type=0>Some Value</b>
</a>
...or...
<a>
<b type=1>Empty</b>
</a>
...or...
<a>
<b type=0>Empty</b>
</a>
what would be best way to do so in Mulesoft?
Using script with lines like
if (payload.a == null ) payload.a={}
if (payload['a']['b']) payload['a']['b']={}
if (payload.a.b.type == null) payload.a.b.type=0;
or dataweave
%dw 1.0
%output application/xml
---
{
a: payload.a default { {b:{ b#type=0 }} }
}
I'm confused about syntax here.

If I understand correctly what you're asking, the following seems to work:
input:
<?xml version='1.0' encoding='UTF-8'?>
<root>
<a>
<b>Some Value</b>
</a>
<a>
<b type="1" />
</a>
<a/>
</root>
Dataweave:
%dw 1.0
%output application/xml
---
root: payload.root.*a mapObject (
a: {
b #(type: $.b.#type default "0"):
$.b when $.b != null and $.b != "" otherwise "Empty"
}
)
output:
<?xml version='1.0' encoding='UTF-8'?>
<root>
<a>
<b type="0">Some Value</b>
</a>
<a>
<b type="1">Empty</b>
</a>
<a>
<b type="0">Empty</b>
</a>
</root>

Related

create xml snippet using dataweave (i.e. remove root element)

desiring an output like this
</b>
<c>
<value1 />
</c>
<c>
<value2 />
</c>
<c>
<value3/>
</c>
instead of this
<a>
</b>
<c>
<value1 />
</c>
<c>
<value2 />
</c>
<c>
<value3/>
</c>
</a>
via dataweave. i understand the output wont necessarily be completely valid xml
any help appreciated thanks
Because it is going to miss a single root element it is not going to be valid XML. So DataWeave is not going to be able to read or write it directly. You can generate an XML for each element and concatenate them as a string to avoid having an XML parsing error.
The input is not valid, I fixed it as this:
<a>
<b/>
<c>
<value1 />
</c>
<c>
<value2 />
</c>
<c>
<value3/>
</c>
</a>
Script:
%dw 2.0
output application/java
---
(payload[0] pluck (value,key,index) -> {(key):value} )
reduce ((item, acc="") -> acc ++ write(item, "application/xml", {"writeDeclaration":false}) ++ "\n" )
Output:
<b/>
<c>
<value1/>
</c>
<c>
<value2/>
</c>
<c>
<value3/>
</c>
Note that I added a newline at the end of each string ("\n") for clarity. You can remove it if you want.

Python etree lxml moving a child from parent

I have xml of the form:
<b>
<a>
<c>some stuff</c>
<d> some more stuff</d>
</a>
</b>
which I want to reformat as:
<b>
<c>some stuff</c>
<a>
<d> some more stuff</d>
</a>
</b>
any ideas on how to do this using Python lxml?
So I finally solved it using dummy tags and the addnext argument:
def new_a(xml):
node_b=xml.xpath('/b')[0]
node_d=xml.xpath('/b/a/d')
node_d[0].addnext(etree.Element('dummy_tag'))
node_dummy=xml.xpath('/b/a/dummy_tag')
node_dummy[0].append(node_d[0])
etree.strip_tags(node_b,'a')
dummies=node_b.findall('dummy_tag')
for node in dummies:
node.tag='a'
return xml
So if:
xml_ini="<b><a><c>some stuff</c><d>some other stuff</d><e>even more stuff</e></a></b>"
xml=etree.fromstring(xml_ini)
xml_new=new_a(xml)
Then we go from this:
<b>
<a>
<c>some stuff</c>
<d>some other stuff</d>
<e>even more stuff</e>
</a>
</b>
To this:
<b>
<c>some stuff</c>
<a>
<d>some other stuff</d>
</a>
<e>even more stuff</e>
</b>

Understanding WebElement.findElement() and XPATH

I want to use the WebElement.findElement() API to locate a node inside the parent node using XPATH //span[#class='child-class']. I thought this would return me the <div> that is inside the parent. However, it is returning me the first one it found in the entire DOM tree. Did I use the wrong XPATH?
I have also tried using .//span[#class='child-class'] as the XPATH, but that does return anything.
Thank you.
UPDATE:
given the HTML below, I want to define a locator for the child-title <span> and child-date <span> and locate them using WebElement.findElement() API regardless of the parent being "//a/li[1]" or "//a/li[2]"
<a>
<li> parent 1
<div>
<span class="child-title child-style">title 1</span>
<span class="child-date child-style"> date 1</span>
<span class="child-author">author 1</span>
</div>
</li>
</a>
<a>
<li> parent 2
<div>
<span class="child-title child-style">title 2</span>
<span class="child-date child-style"> date 2</span>
<span class="child-author">author 3</span>
</div>
</li>
</a>
<a>
<li> parent 3
<div>
<span class="child-title child-style">title 3</span>
<span class="child-date child-style"> date 3</span>
<span class="child-author">author 3</span>
</div>
</li>
</a>
I have a WebElement parent2 initialized and located using "//a/li[2]",
WebElement child = parent2.findElement(By.xpath("//span[#class='child-author']")); would give me "author 1"
WebElement child = parent2.findElement(By.xpath("span[#class='child-author']")); would give me NoSuchElementException
There are my 2 comments with your sample code
1 - With your posted HTML, the xpath //a/li[2] is not found (we only have 3 elements with //a/li[1])
2 - Assume that we do have right code, you need to understand the differences between single slash and double slash in Xpath
a/b (single slash): select element that has "tag b" and "stands right after" an element that has "a tag"
E.g.:
<a>
<b>
<d>
<c>
</c>
</d>
</b>
</a>
AND
a//b (double slash): select element that has "tag b" and is n-level-child an element that has "a tag"
E.g.:
<a>
<c>
<d>
<b>
</b>
</d>
</c>
</a>
So, with your code
<a>
<li> parent 1
<div>
<span class="child-title child-style">title 1</span>
<span class="child-date child-style"> date 1</span>
<span class="child-author">author 1</span>
</div>
</li>
</a>
If you want to get Date Info, you should use
WebElement parent = driver.findElement(By.xpath("//a/li"));
WebElement date = parent.findElement(By.xpath("div/span[contains(#class, 'child-date')]"));
WebElement date = parent.findElement(By.xpath("//span[contains(#class, 'child-date')]"));
The code
WebElement date = parent.findElement(By.xpath("span[contains(#class, 'child-date')]"));
Will bring out NoSuchElementException because there is no [span] tag right after [li] tag
Hope help
Try something like:
Use dot(.) before double slash(//)
It looks for child under the given parent element.
Completely new question ... completely new answer. :(
Try something like:
WebElement parent1 = driver.findElement(By.xpath("//a[1]/li")); // use a[2] for parent2
WebElement author = parent1.findElement(By.xpath("span[#class='child-author']"));
WebElement date = parent1.findElement(By.xpath("span[contains(#class, 'child-date')]"));
WebElement title = parent1.findElement(By.xpath("span[contains(#class, 'child-title')]"));
Try something like :
//a/li[contains(text(), 'parent 1')]/div
It requests for "the <div> inside a <li> whose text contains 'parent 1' and who is inside a <a>.
It might not work if you have more parents because it works with a contains() (this xpath would also select <li> parent 10 ... </li>). It would be better if "parent x" were an attribute of the <li> instead of its text.

Schema.org price and SPARQL

I have the following HTML with Schema.org RDFa:
<li class="product" typeof="s:Product">
<a href="item.php?id=227">
<img property="s:img" src="http://www.test.com/pictures/227.jpg"></a>
<h2 property="s:name">Example name</h2>
<div property="s:brand">Examplebrand</div>
<div property="s:model">Examplemodel</div>
<div rel="s:offers">
<div class="description" typeof="s:Offer">
<div property="s:price">79,00</div>
<div property="s:priceCurrency" content="EUR"></div>
</div>
</div>
<div property="s:productID" content="NQ==">
<div rel="s:seller">
<div class="description" typeof="s:Organization">
<div property="s:name">Shop1</div>
</div>
</div>
</div>
</li>
After loading the page I want to use SPARQL to select all the products which are (for example) > €70,00.
But this only gives back NULL:
PREFIX s: <http://schema.org/>
SELECT ?a ?price
WHERE {
?a s:price ?price.
FILTER (?price > 70).
}
I think it's not interpreting the price as an price/float. What am I doing wrong?
The XHTML isn't enough for us to get the corresponding RDF data from the RDFa. I've filled out your XHTML into the following. Note that I've make the s prefix be http://schema.org/ based on your SPARQL query. However, if those prefixes don't line up in your data, that would be an easy place for things to break down.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.1//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-2.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
version="XHTML+RDFa 1.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:s="http://schema.org/"
xsi:schemaLocation="http://www.w3.org/1999/xhtml
http://www.w3.org/MarkUp/SCHEMA/xhtml-rdfa-2.xsd"
lang="en"
xml:lang="en">
<head><title>Some title</title></head>
<body>
<li class="product" typeof="s:Product">
<a href="item.php?id=227">
<img property="s:img" src="http://www.test.com/pictures/227.jpg"/></a>
<h2 property="s:name">Example name</h2>
<div property="s:brand">Examplebrand</div>
<div property="s:model">Examplemodel</div>
<div rel="s:offers">
<div class="description" typeof="s:Offer">
<div property="s:price">79,00</div>
<div property="s:priceCurrency" content="EUR"></div>
</div>
</div>
<div property="s:productID" content="NQ==">
<div rel="s:seller">
<div class="description" typeof="s:Organization">
<div property="s:name">Shop1</div>
</div>
</div>
</div>
</li>
</body>
</html>
Putting that into the W3C's RDFa distiller, we can get this RDF:
<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:s="http://schema.org/"
xmlns:xhv="http://www.w3.org/1999/xhtml/vocab#"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
<rdf:Description rdf:about="http://www.test.com/pictures/227.jpg">
<s:img xml:lang="en"></s:img>
</rdf:Description>
<s:Product>
<s:seller>
<s:Organization>
<s:name xml:lang="en">Shop1</s:name>
</s:Organization>
</s:seller>
<s:productID xml:lang="en">NQ==</s:productID>
<s:model xml:lang="en">Examplemodel</s:model>
<s:offers>
<s:Offer>
<s:priceCurrency xml:lang="en">EUR</s:priceCurrency>
<s:price xml:lang="en">79,00</s:price>
</s:Offer>
</s:offers>
<s:name xml:lang="en">Example name</s:name>
<s:brand xml:lang="en">Examplebrand</s:brand>
</s:Product>
</rdf:RDF>
Looking at the RDF, it's easy to see why the price is being interpreted as a string:
<s:price xml:lang="en">79,00</s:price>
The property value is a string, and a string with a language tag at that! You can specify the datatype easily, however, by adding the namespace and a datatype attribute:
<html xmlns="http://www.w3.org/1999/xhtml"
version="XHTML+RDFa 1.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
...>
...
<div property="s:price" datatype="xsd:float">79,00</div>
...
</html>
However, the comma notation isn't actually legal for the xsd:float type, so you'll actually need to specify a content attribute too, as in:
<div property="s:price" datatype="xsd:float" content="79.00">79,00</div>
After those changes, you'll get this RDF:
<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:s="http://schema.org/"
xmlns:xhv="http://www.w3.org/1999/xhtml/vocab#"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
<s:Product>
<s:productID xml:lang="en">NQ==</s:productID>
<s:model xml:lang="en">Examplemodel</s:model>
<s:brand xml:lang="en">Examplebrand</s:brand>
<s:offers>
<s:Offer>
<s:priceCurrency xml:lang="en">EUR</s:priceCurrency>
<s:price rdf:datatype="http://www.w3.org/2001/XMLSchema#float">79.00</s:price>
</s:Offer>
</s:offers>
<s:name xml:lang="en">Example name</s:name>
<s:seller>
<s:Organization>
<s:name xml:lang="en">Shop1</s:name>
</s:Organization>
</s:seller>
</s:Product>
<rdf:Description rdf:about="http://www.test.com/pictures/227.jpg">
<s:img xml:lang="en"></s:img>
</rdf:Description>
</rdf:RDF>
After those changes, your query works just fine with no modifications:
$ arq --data data3.rdf --query query.sparql
------------------------------------------------------------
| a | price |
============================================================
| _:b0 | "79.00"^^<http://www.w3.org/2001/XMLSchema#float> |
------------------------------------------------------------

Double if condition in Spry Region

<div spry:region="ds1" spry:repeatchildren="ds1">
<b spry:if=" '{title}'!='' ">
<!-- this is the first if -->
<a href="#" spry:if=" '{author}'!='' ">{author}
<!-- this is the second if -->
</a>
</b>
</div>
I wonder if there is any method as simple as
if(x==y && i>j)
in
<b>spry</b>
region.
I can't find any information in spry docs (labs.adobe.com/technologies/spry/)
The syntax inside the spry:if attribute is Javascript, so you can use &&:
<b spry:if="'{title}' != '' && '{author}' != ''">
<!-- ... -->
</b>
also you can call a function instead
spry:if="myFunc();"
and in your function return Boolean value as result
function myfunc()
{
//do somethings ;
if(...)
return true;
else
return false;
}
Normally I do like this
<div spry:region="ds1" spry:repeatchildren="ds1">
<b spry:if=" '{ds1::title}'!='' && '{ds1::author}'!=''">
{author}
</b>
</div>