I have the following XML file:
<Body>
<ELEMENT Property1="A" Property2="B" Property3="C"/>
<ELEMENT Property1="D" Property2="E" Property3="F"/>
<ELEMENT Property1="G" Property2="H" Property3="I"/>
</Body>
And I'm trying to have a one string object all of the properties values ordered like this:
A,B,C;D,E,F;G,H,I
I basically need to have each ELEMENT properties seperated by a semicolon.
How to do that?
You can try below expression
string-join((string-join(//ELEMENT/#Property1, ','), string-join(//ELEMENT/#Property2, ','), string-join(//ELEMENT/#Property3, ',')), ';')
Output:
A,D,G;B,E,H;C,F,I
or
string-join((string-join(//ELEMENT[1]/#*, ','), string-join(//ELEMENT[2]/#*, ','), string-join(//ELEMENT[3]/#*, ',')), ';')
output:
A,B,C;D,E,F;G,H,I
Since I wanted , between the properties and ; between the ELEMENTs, here's the required solution for an undefined number of ELEMENTs :
string-join(for $x in //ELEMENT return string-join($x/#*,','), ';')
The result is
A,B,C;D,E,F;G,H,I
Related
<Cities>
<city>
<name />
<country />
<population asof = "2019" />
<total> 2918695</total>
<Average_age> 28 </Average_age>
</city>
<city>
<name />
<country />
<population asof = "2020" />
<total> 78805467 </total>
<Average_age> 32 </Average_age>
</city>
</Cities>
I want to build a Xpath query which returns the total population of cities where asof is higher than 2018
Try this XPath-1.0 expression:
sum(/Cities/city[population/#asof > 2018]/total)
Or, another, less specific, version:
sum(//city[population/#asof > 2018]/total)
the expression to grab population with asof attribute greater than 2018 would be:
//population[#asof > '2018']
If you looking for <total> which is a sibling of <population> despite your indentation use following-sibling::total after the expression
otherwise use /total
lets follow the first approach so the XPath continues as:
//population[#asof > '2019']/following-sibling::total
and add /text() at the end to get text inside of desired <total> tag. additionally if you want sum of populations you can put the whole expression inside sum() function. the inside expression of sum gonna be like:
//population[#asof > '2019']/following-sibling::total/text()
<results>
{
for $p in
(
for $o in doc("mondial-3.0.xml") /mondial/organization
where fn:count($o/members)
order by fn:count($o/members) descending
return <organization>
<name> {$o/#name/string()} </name>
<abbreviation> {$o/#abbrev/string()} </abbreviation>
<num_members> {fn:count($o/members)} </num_members>
<members> {for $m in doc("mondial-3.0.xml") $o/members
return <country> {mondial/country[#id=$m/#country]/#name/string()} </country>} </members>
</organization>
)[position() < 10]
return $p
}
</results>
I am unable to access the ancestor node in this problem as I have got an id stored of a parameter and now I want to match the id of that parameter and get a name of the parameter.
I am not getting any output for this. I am not sure where I am going wrong.
XML FILE :-
The link for the xml file is https://raw.githubusercontent.com/kroell/hsrm-mi-2semester-markuplanguage/master/Abgabe2/Aufgabe2/mondial-3.0.xml
In the link you posted, the root element of the XML is mondial not users, so I'd use mondial in this answer. Notice that member of organization and country are linked by country id, so you can do as follow to get country name of every member element :
<f>
{
for $m in $o/members
return <g> {mondial/country[#id=$m/#country]/#name/string()} </g>
}
</f>
Here is the complete working query. Tested in http://www.xpathtester.com/xquery using XML from the link posted in question as input :
<a>
{
for $p in
(
for $o in /mondial/organization
where fn:count($o/members)
order by fn:count($o/members) descending
return <b>
<c> {$o/#name/string()} </c>
<d> {$o/#abbrev/string()} </d>
<e> {fn:count($o/members)} </e>
<f> {for $m in $o/members
return <g> {/mondial/country[#id=$m/#country]/#name/string()} </g>} </f>
</b>
)[position() < 10]
return $p
}
</a>
You don't define the desired output of your query so it's hard to tell you why your query isn't giving the desired output; but there are several things about the query that suggest it's completely wrong.
Firstly, $o is always a single <mem> element, so fn:count($o) is always 1, so the use of this expression in the where and order by clauses cannot have any useful effect.
Secondly, the expression used to produce the content of the <f> element looks all wrong because it doesn't depend in any way on the value of $o.
Is there any way that i can use an expression inside expression in Freemarker?
Example:
XML FIle
<Document>
<Row>
<item_date>01/01/2015</item_date>
</Row>
<Row>
<item_date>02/01/2015</item_date>
</Row>
</Document>
<#list 0..1 as i>
${Document.Row[${i}].item_date}
</#list>
I want to print as below
01/01/2015
02/01/2015
Any idea?
Thanks in Advance
Like this:
${Document.Row[i].item_date}
Note that if you are using an up-to-date version, you get this error message, which explains why:
You can't use "${" here as you are already in
FreeMarker-expression-mode. Thus, instead of ${myExpression}, just
write myExpression. (${...} is only needed where otherwise static text
is expected, i.e, outside FreeMarker tags and ${...}-s.)
In case below two elements do not show in same time
<a title='a' />
<b title='b' />
I want to check if one of them can show
does xpath support the 'or' function? I just want to write in one line:
//a[#title='a'] or .. #title='b' ??
XPath Operators
Select either matching nodes (your case here):
//a[#title='a'] | //b[#title='b']
Select one element with either matching attributes
//a[#title='a' or #title='b']
If you want to match either <a/> elements with #title='a' attribute or <b/> elements with #title='b' attribute, you can also match all elements and perform a test on their name:
//*[local-name(.) = 'a' and #title='a' or local-name(.) = 'b' and #title='b']
I have an xpath-expression like this:
element[#attr="a"] | element[#attr="b"] | element[#attr="c"] | … which is an »or« statement. So can I create an expression that guarantees the result to appear in the order as in the query, even if the elements appear in a different order in the document?
f.e. an document fragment in this order:
<doc>
<element attr="c" />
<element attr="b" />
<element attr="a" />
.
.
.
</doc>
and a result list ordered like this:
[0] <element attr="a" />
[1] <element attr="b" />
[2] <element attr="c" />
.
.
.
The | operator computes the union of its operands and with XPath 1.0 you simply get a set of nodes, the order is undefined, though most XPath APIs then return the result in document order or allow you to say which order you want or whether order matters (see for instance http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#XPathResult).
With XPath 2.0 you get a sequence of nodes ordered in document order, with XPath 2.0 if you want the order of your subexpressions you would need to use the comma operator, not the union operator i.e. element[#attr="a"] , element[#attr="b"] , element[#attr="c"].
can I create an expression that guarantees the result to appear in the
order as in the query, even if the elements appear in a different
order in the document?
Not with any XPath 1.0 engine -- they return the resulting XmlNodeList in document order.
With XPath 2.0 one can specify that a sequence is to be returned, using the comma , operator, like this:
element[#attr="a"] , element[#attr="b"] , element[#attr="c"]
Finally, If you are limited with an XPath 1.0 implementation, one way of getting the results in the desired order is to evaluate these three XPath expressions:
element[#attr="a"]
element[#attr="b"]
element[#attr="c"]
Then you can access the first result first, the second result -- second and the third result -- third.