How to append a delimiter between multiple values coming from a repeating field in xquery - xpath

I have a xml file which has a repeating element generating multiple values.
I would like to split all the values generated from that xpath delimited by any delimiter like , |_
I have tried the following which did not work -
tokenize(/*:ShippedUnit/*:Containment/*:ContainerManifest/*:Consignments/*:Consignment/*:ConsignmentHeader/*:ConsignmentRef, '\s')
replace(/*:ShippedUnit/*:Containment/*:ContainerManifest/*:Consignments/*:Consignment/*:ConsignmentHeader/*:ConsignmentRef," ","_")
example :
Now getting - CBR123 CBR678 CBR656
Expecting to get - CBR123|CBR678|CBR656
Note : In some transactions, there can be only one value present for that xpath. And therefore replace doesnot work here

To achieve the expected result assuming the sample source XML added to the comments in the original post, use the fn:string-join() function:
string-join(
//ConsignmentRef,
"|"
)
This will return:
CBR00464833N|CBR01264878K
For more on this function, see https://www.w3.org/TR/xpath-functions-31/#func-string-join.

Another option in XQuery 3.1 would be
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:method 'text';
declare option output:item-separator '|';
//ConsignmentRef

Related

Fetch value from XML using dynamic tag in ESQL

I have an xml
<family>
<child_one>ROY</child_one>
<child_two>VIC</child_two>
</family>
I want to fetch the value from the XML based on the dynamic tag in ESQL. I have tried like this
SET dynamicTag = 'child_'||num;
SET value = InputRoot.XMLNSC.parent.(XML.Element)dynamicTag;
Here num is the value received from the input it can be one or two. The result should be value = ROY if num is one and value is VIC if num is two.
The chapter ESQL field reference overview describes this use case:
Because the names of the fields appear in the ESQL program, they must be known when the program is written. This limitation can be avoided by using the alternative syntax that uses braces ( { ... } ).
So can change your code like this:
SET value = InputRoot.XMLNSC.parent.(XMLNSC.Element){dynamicTag};
Notice the change of the element type as well, see comment of #kimbert.

JMeter XPath getting multiple values and odd output order

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

How to display the text from XMLTYPE Column including the spaces using oracle query

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;

XPath2: A sequence of more than one item is not allowed as the first argument of string()

I have this xml that contains certificates and its attributes. Here is the xml over which I am running the extraction query
<Certificates>
<CertificateAndChain>
<Certificate>
<FriendlyName />
<Thumbprint>EE8B375347FCADDC25547FDDF61866E07D5B6A71</Thumbprint>
<SerialNumber>256BB11DB5BE889E46EBCD85608DA849</SerialNumber>
<Version>3</Version>
<SignatureAlgorithm>sha1RSA</SignatureAlgorithm>
<Issuer>CN=certname</Issuer>
<Subject>CN=certname</Subject>
<NotAfter>2040-09-26T18:30:00Z</NotAfter>
<NotBefore>2016-09-27T18:30:00Z</NotBefore>
<IsVerified>false</IsVerified>
</Certificate>
.
.
.(continued)...
I have written another test over this xml that needs to extract thumbprints of all the certificates that are about to get expired in next 10 days.
As part of the test, , I have written the Extraction query as:
<XPath2ResponseParameter Name="TPName"><ExtractionQuery><![CDATA[string(//CertificateAndChain/Certificate[NotAfter[text() <= (current-dateTime() + xs:dayTimeDuration('P10D'))]]/Thumbprint)]]></ExtractionQuery></XPath2ResponseParameter>
The test is in xml file as well. However, when I run the test, I get this exception:
A sequence of more than one item is not allowed as the first argument of string().
This is probably happening because there are multiple certificate elements present in the xml. So, I couldn't figure out the way to extract all the thumbprints failing the mentioned condition(there could be more than 1 and I need to extract all of them)
Can anyone help me fix this?
You can invoke function in axis when using XPath 2.0. So, try to move string() function to the end of the inner XPath (formatted for readability) :
//CertificateAndChain
/Certificate[
NotAfter[
text() <= (current-dateTime() + xs:dayTimeDuration('P10D'))
]
]/Thumbprint
/string()
UPDATE :
Since CDATA can't receive multiple strings in this context, according to the error message in your first comment, then you need to combine those strings into one, presumably using string-join() :
string-join(
//CertificateAndChain
/Certificate[
NotAfter[
text() <= (current-dateTime() + xs:dayTimeDuration('P10D'))
]
]/Thumbprint
/string()
,' ')

Array concatenation in IBM Filenet P8 Expression Builder?

In the Expression Builder for the Workplace Process Designer, I have an attachment variable of type String[] (array of strings). I'd like to add some elements to it using the Expression Builder, but I can't work out the syntax. Has anyone done this? Is it even possible to add elements to an existing array in Expression Builder?
The arraytostring solution only works if there is only one element the array.
Assign the additional value with the following expression:
stringarray[elementcount(stringarray) + 1] = value
The expected 'array out of bound exception' and the resizing of the array is handled during the assignment.
I originally thought that it is not possible that we had to resort to have a custom java component to do the job, however I had run a small experiment that should serve as a workaround for your case.
Suppose you have String[] arrayType={"string1, string2"}, you can use the following expression as a value for your updated array:
{(arraytostring(arrayType, " ", " ,", ","))+"string3"}
What I did was that,
First, I used arraytostring function to convert the array to a string separated by comma with a comma left at the end. My output is similar to string1,string2,
Second, I appended the string that I want to add to the end of the string, so that my output is string1,string2,string3
Lastly, I assigned the value above to my array, using the array expression format {}, so my final evaluated string is {string1,string2,string3}
For more information about array functions, please follow the link below:
https://www.ibm.com/support/knowledgecenter/SSNW2F_5.2.1/com.ibm.p8.pe.user.doc/bpfe003.htm
I had a case like this, here is what I did:
I get the array from the attachment using the CE-Operation and store
in an array property on the workflow
Then I used the following to
{(arraytostring(workflowArray, " ", " ,", ","))+workflowStringProp}
using the CE-Operation again to set the array in the attachment with
the workflowArray.

Resources