I have xml stored in a xmltype table in a (Oracle Database) if the database matters
<?xml version="1.0"?>
<myDate xmlns="http://www.example.com/schema" dateTimeProc="20100824T102806" Num="666" timId="4" procId="1" proces="501">
</myDate>
<?xml version="1.0"?>
<myDate xmlns="http://www.example.com/schema" dateTimeProc="20101110T102806" Num="666" timId="4" procId="1" proces="501">
</myDate>
I would like to know whats the xpath expression to get all xml's that are between certain dates something like
select * from XMLTable
where existsNode(object_value,'myDate[#dateTimeProc]')
between sysdate-120 and sysdate-90
I was interested so I started looking around. Apparently according to http://www.eggheadcafe.com/articles/20030627d.asp the AND directive is allowable in an xpath query.
I know that you can use > and < in the queries (according to http://www.w3schools.com/xpath/xpath_syntax.asp)
So I would try:
//myDate[#dateTimeProc < X and #dateTimeProc > Y]
(where X and Y are a unix timecode that you get out of whatever code/language you're using)
Related
Preamble
I have a JMeter script with an XPath Extractor, in this I have specified a query that gets multiple values from the XML document. This all works fine
XML
<?xml version="1.0" encoding="UTF-8"?>
<InventoryAvailabilityAdvice>
<Warehouse>WFC2</Warehouse>
<Timestamp>2019-07-31T23:00:02.177</Timestamp>
<InventoryItem>
<ItemNumber>80903</ItemNumber>
<AvailableQuantity UnitOfMeasure="EA">13</AvailableQuantity>
</InventoryItem>
<InventoryItem>
<ItemNumber>80901</ItemNumber>
<AvailableQuantity UnitOfMeasure="EA">17</AvailableQuantity>
</InventoryItem>
</InventoryAvailabilityAdvice>
Problem
When I then try to get these values in a loop using a JSR232 Sampler they don't seem to come out in the order declared in the XPath Query.
I expected theData_2 to contain the UnitOfMeasure attribute and theData_3 to contain the quantity, but as you can see they are reversed.
Question
Is this expected behavior? If so, when an element has multiple attributes how do I know which order those will be made available as?
Thanks
The order of XPath nodesets produced by union operator is not guaranteed, you can see putValuesForXPathInList() function for implementation details
Actually if you've decided to go for Groovy - you don't even need the XPath Extractor, you can use XmlSlurper class for parsing the XML response.
Example code:
def response = new XmlSlurper().parseText(prev.getResponseDataAsString())
response.InventoryItem.eachWithIndex { item, index ->
log.info('Item: ' + index)
log.info('ItemNumber: ' + item.ItemNumber)
log.info('AvailableQuantiry: ' + item.AvailableQuantity)
log.info('UnitOfMeasure:' + item.AvailableQuantity.#UnitOfMeasure)
}
Demo:
References:
Groovy: Processing XML
Apache Groovy - Why and How You Should Use It
I am trying to use XPath 1.0 to select the maximum double value in an XML document. I understand that XPath 1.0 doesn't support the Max function that would make this extremely easy, but the system I'm using only supports XPath 1.0 functions.
I'm not able to post the entire file due to length, but here is a sample of the document I'm scanning: https://codebeautify.org/xmlviewer/cbc93c7e.
I've tried this XPath Expression:
/site/forecast/datum[not(primary < preceding-sibling::datum/primary) and not (primary < following-sibling::datum/primary)]
But no matter what, it returns the wrong datum. It always returns:
<datum>
<valid timezone="UTC">2019-04-04T06:00:00-00:00</valid>
<primary name="Stage" units="ft">9.80</primary>
<secondary name="Flow" units="cfs">3010.00</secondary>
<pedts>HGIFE</pedts>
</datum>
I expect it to return the element with the maximum "primary stage" value like:
<datum>
<valid timezone="UTC">2019-03-28T18:00:00-00:00</valid>
<primary name="Stage" units="ft">13.10</primary>
<secondary name="Flow" units="cfs">13400.00</secondary>
<pedts>HGIFE</pedts>
</datum>
I understand it will return all those with the 13.10 primary stage, but that's okay. I'll select the first one it returns if I can just get it to that point.
Do note that you might have more than one maximum. Use:
/site/forecast/datum[not(primary < ../datum/primary)][1]
This select the element
<datum>
<valid timezone="UTC">2019-03-28T18:00:00-00:00</valid>
<primary name="Stage" units="ft">13.10</primary>
<secondary name="Flow" units="cfs">13400.00</secondary>
<pedts>HGIFE</pedts>
</datum>
Test it in http://www.xpathtester.com/xpath/4256aac47f4f0efc36e23a2f16183d90
I have XML Data type column with the below data in it, and i want to extract the data from below XML including the spaces between the tags. after there is one space like that after math_expression also there is one space.
when i used Extract function to extract the data from the below XML it is eliminating the spaces.
Example XMLTYPE Data column:
<quantity_a> <math_expression> <math display="inline" overflow="scroll"> <mrow> <mn>3</mn> <mi>x</mi> <mo>+</mo> <mn>2</mn>
</mrow> </math> </math_expression> </quantity_a>
Output i Want is:
" 3 X + 2 "
Appreciate your help on this.
String-join - description
/quantity_a/math_expression/math/mrow/* - it returs all elements from mrow node.
select xmlquery('string-join( /quantity_a/math_expression/math/mrow/*/text()," ")' passing xmltype('<quantity_a>
<math_expression>
<math display="inline" overflow="scroll">
<mrow> <mn>3</mn> <mi>x</mi> <mo>+</mo> <mn>2</mn>
</mrow> </math> </math_expression> </quantity_a>') returning content ) from dual;
My problem is the following :
I usually have those data:
<structures>
<structure id="10">
<code>XXX</code>
</structure>
</structures>
so the table I display (single columns : code) is ok.
But in some cases, the data is the result a a query with no content, so the data is:
<structures/>
resulting in my table not displaying + error.
I am trying to insert, in the case of an empty instance, a single node so that the data would look like:
<structures>
<structure id="0"/>
</structures>
I am trying something like that :
<xforms:action ev:event="xforms-submit-done">
<xforms:insert if="0 = count(instance('{./instance-name}')/root/node())" context="instance('{./instance-name}')/root/node()" origin="xforms:element('structure', '')" />
</xforms:action>
but no node inserted when I look at the data in the inspector in the page.
Any obvious thing I am doing wrong?
There seems to be erros in your XPath if and context expressions:
if="0 = count(instance('{./instance-name}')/root/node())"
context="instance('{./instance-name}')/root/node()"
You are a using curly brackets { and }, I assume to have the behavior of attribute value templates (AVTs). But the if and context expressions are already XPath expressions, so you cannot use AVTs in them. Try instead:
if="0 = count(instance(instance-name)/root/node())"
context="instance(instance-name)/root/node()"
Also, the instance-name path is relative to something which might not be clear when reading or writing the expression. I would suggest using an absolute path for example instance('foo')/instance-name to make things clearer.
You don't provide the structure of the other instances, so I can tell for sure, but you'll expression above suppose that they have the form:
<xf:instance id="foo">
<some-root-element>
<root>
<structure/>
</root>
<some-root-element>
</xf:instance>
I don't know if that's what you intend.
Finally, you could replace count(something) = 0, with empty(something).
I am little new to linq and was wondering how i can select the application in the following xml based on the application name using Extension Methods (not using the query expression)
<applicationlist>
<application>
<name>test1</name>
<ele1>852</ele1
<ele2>http://localhost/test1</ele2>
</application>
<application>
<name>test2</name>
<ele1>456</ele1
<ele2>http://localhost/test2</ele2>
</application>
</applicationlist>
Assuming that by "the SQL way of selecting" you mean "using a query expression", let's start off with your query expression:
var v = from b in root.Descendants("application")
where b.Element("name").Value.Trim().ToLower() == appName.Trim().ToLower()
select b;
With extension methods, this would just be:
var v = root.Descendants("application")
.Where(b => b.Element("name").Value.Trim().ToLower() ==
appName.Trim().ToLower());
I would recommend against making case-insensitive comparisons this way though - it has cultural problems. Use something like this instead:
var v = root.Descendants("application")
.Where(b => b.Element("name").Value.Trim().Equals(appName.Trim(),
StringComparison.CurrentCultureIgnoreCase);
(or one of the other StringComparison options - or an instance of StringComparer).
You might also want to trim appName once rather than for every comparison...