soapui how to get the list of nodes by using local-name in xpath expression? - xpath

I am using soapui for automation testing. I am trying to write a xpath expression to do the property transfer with following xml
<snapshots query="after=2014-04-16 12:30:00-0700" mask="op" xmlns="http://ws.example.com/roma/201907" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<AsOf>2014-04-16T19:20:44-07:00</AsOf>
<offers>
<offer entityId="6500588"/>
<offer entityId="6500589"/>
<offer entityId="6500590"/>
<offer entityId="6557335">
<rubber>KJM</rubber>
<code>B44733</code>
<offerCode>PA</offerCode>
<status name="Completed">C</status>
<startDate basis="GMT-4">2013-04-01</startDate>
<endDate basis="GMT-4">2014-04-15</endDate>
<template>
<sourceKey-Ref entityId="36KTV" code="KPA513C36KTV" uri="/snapshot/sourcekey/36KTV"/>
<pTemplateCode>PPAKXC</pTemplateCode>
<panelCode>HPA5LTM</panelCode>
<itemCode>PA1467</itemCode>
</template>
<venue code="28">
<supervenue>5</supervenue>
</venue>
<currencyDetail currency="USD">
<unitPrice>29.95</unitPrice>
<numberPayments>1</numberPayments>
</currencyDetail>
<hData>
<legacyScriptCode>300</legacyScriptCode>
<hpKeycode>189161</hpKeycode>
<hpProductNumber>014399</hpProductNumber>
<hpMpgCode>300</hpMpgCode>
</hData>
</offer>
<offer entityId="6557336">
<rubber>KJM</rubber>
<code>B44734</code>
<offerCode>VY</offerCode>
<status name="Completed">C</status>
<startDate basis="GMT-4">2013-04-01</startDate>
<endDate basis="GMT-4">2014-04-15</endDate>
<template>
<sourceKey-Ref entityId="36KTV" code="KPA513C36KTV" uri="/snapshot/sourcekey/36KTV"/>
<pTemplateCode>PPAKXC</pTemplateCode>
<panelCode>HPA5LTM</panelCode>
<offerCode>OVYC8UM9</offerCode>
<itemCode>VY4023</itemCode>
</template>
<venue code="28">
<supervenue>5</supervenue>
</venue>
<currencyDetail currency="USD">
<unitPrice>0.00</unitPrice>
<numberPayments>1</numberPayments>
</currencyDetail>
<hData>
<legacyScriptCode>947</legacyScriptCode>
<hpKeycode>189162</hpKeycode>
<hpProductNumber>602185</hpProductNumber>
<hpMpgCode>947</hpMpgCode>
</hData>
</offer>
<offer entityId="6557337">
<rubber>KJM</rubber>
<code>B44736</code>
<offerCode>VY</offerCode>
<status name="Completed">C</status>
<startDate basis="GMT-4">2013-04-01</startDate>
<endDate basis="GMT-4">2014-04-15</endDate>
<template>
<sourceKey-Ref entityId="36KTV" code="KPA513C36KTV" uri="/snapshot/sourcekey/36KTV"/>
<pTemplateCode>PPAKXC</pTemplateCode>
<panelCode>HPA5LTM</panelCode>
<offerCode>OVYC8UMA</offerCode>
<itemCode>VY4012</itemCode>
</template>
<venue code="28">
<supervenue>5</supervenue>
</venue>
<currencyDetail currency="USD">
<unitPrice>0.00</unitPrice>
<numberPayments>1</numberPayments>
<firstPaymentAmount>0.00</firstPaymentAmount>
<firstShippingAmount>5.98</firstShippingAmount>
</currencyDetail>
<hData>
<legacyScriptCode>947</legacyScriptCode>
<hpKeycode>189163</hpKeycode>
<hpProductNumber>602094</hpProductNumber>
<hpMpgCode>947</hpMpgCode>
</hData>
</offer>
</offers>
</snapshots>
I would like to have all hpKeycode using local-name() in the XPath expression. I tried
//*[local-name()='hpKeycode']
but this gives me only the first node which is 189161. This
/*[local-name()='hpKeycode'][2]
also does not work. Any help would be greatly appreciated.

You can try with XQuery. In the property transfer step select Use XQuery checkbox as you see in the image below. And use this code:
declare namespace soap='http://schemas.xmlsoap.org/soap/envelope/';
declare namespace ns1='http://ws.example.com/roma/201907';
<ns1:offer>
{
for $id in //*[local-name()='hpKeycode'] return string($id)
}
</ns1:offer>
EDIT:
If you want to avoid the use of XQuery, you can add three Transfers on your property transfer, on each one use:
First id
(//*[local-name()='hpKeycode'])[1]
Second id
(//*[local-name()='hpKeycode'])[2]
Third id
(//*[local-name()='hpKeycode'])[3]
Hope this helps,

This would not work in the way you expect it to because you are pulling a single set of values. You would need to specify what node branch you want further up the tree.
Its like road ways... if you were giving someone directions you would need to inform them which way to go for each fork in the road. Lets say you wanted to tell them how to get to one of 3 possible airports each located in a different city. If you said "as you arrive at airports 1,2, and 3 enter the 2nd". They would be baffled and say something like "what city though?" and maybe "its not possible for them to exist in the same location".
Solution:
Here is what you would want given the xml you provided (both work in soapui).
Xpath 2.0
//*:offer[4]/*:hData/*:hpKeycode
//*:offer[5]/*:hData/*:hpKeycode
//*:offer[6]/*:hData/*:hpKeycode
Xpath 1.0
//*[local-name()='offer'][4]/*[local-name()='hData']/*[local-name()='hpKeycode']
//*[local-name()='offer'][5]/*[local-name()='hData']/*[local-name()='hpKeycode']
//*[local-name()='offer'][6]/*[local-name()='hData']/*[local-name()='hpKeycode']
Hope this more detailed explanation helps!

Related

How to check if a element exists in xml using xpath

This is my XMl file and I want to know if the Element "SCENE" which has has a value "SCENE_TestSene" exists.
This is my current code.
if (xmlDoc.SelectSingleNode("//DATABASE/SCENE") == null).......
but I am not able to figure out how to check for the scene name in the xpath ?
<DATABASE>
<SCENE SCENE_NAME="SCENE_TestSene">
<TEMPLATE_Test>
<Image1>C:\Temp\Pitch_Positions.jpg</Image1>
<text1>DDASD</text1>
<text2>ADASDSA</text2>
</TEMPLATE_Test>
</SCENE>
<SCENE SCENE_NAME="SCENE_NewSene">
<TEMPLATE_Test1>
<Image1>C:\Temp\Pitch_Positions.jpg</Image1>
<text1>DDASD</text1>
<text2>ADASDSA</text2>
</TEMPLATE_Test1>
</SCENE>
</DATABASE>
Instead of
"//DATABASE/SCENE"
try
"//DATABASE/SCENE[#SCENE_NAME='SCENE_TestSene']"

How to loop xml nodes using ruby

I have an XML file of 50MB. I need to parse it and convert to CSV.
Following is the XML File
<?xml version="1.0" encoding="ISO-8859-1"?>
<IAPDFirmStateReport GenOn="2019-01-02">
<Firms>
<Firm>
<Info FirmCrdNb="146099" BusNm="PRINCIPA FINANCIAL ADVISORS" LegalNm="CHUNG, BUCK CHWEE"/>
<MainAddr Strt1="15111 WHITTIER BLVD" Strt2="STE 420" City="WHITTIER" State="CA" Cntry="United States" PostlCd="90603" PhNb="562-945-7888" FaxNb="562-968-1885"/>
<MailingAddr/>
<StateRgstn>
<Rgltrs>
<Rgltr Cd="CA" St="APPROVED" Dt="2008-03-13"/>
</Rgltrs>
</StateRgstn>
<ERA>
<Rgltrs/>
</ERA>
</Firm>
<Firm>
<Info FirmCrdNb="170562" SECNb="802-112318" BusNm="ALUMNI VENTURES GROUP" LegalNm="LAUNCH ANGELS MANAGEMENT COMPANY, LLC"/>
<MainAddr Strt1="788 ELM ST" City="MANCHESTER" State="NH" Cntry="United States" PostlCd="03101" PhNb="603-518-8112"/>
<MailingAddr Strt1="889 ELM ST" Strt2="3RD FLOOR" City="MANCHESTER" State="NH" Cntry="United States" PostlCd="03101"/>
<StateRgstn>
<Rgltrs/>
</StateRgstn>
<ERA>
<Rgltrs>
<Rgltr Cd="MA" St="ACTIVE" Dt="2014-02-24"/>
<Rgltr Cd="NH" St="ACTIVE" Dt="2018-07-23"/>
</Rgltrs>
</ERA>
</Firm>
<`/Frims>`
------Almost having 90 Firm tags
So, I need to parse it dynamically using ruby and convert it into CSV. How can I figure out this?
Look at this question - Parsing XML with Ruby
You may also use Ox gem which is not mentioned in above question - take a look here:
https://github.com/ohler55/ox#parsing-xml-into-a-hash-fast
Once you will have your XML converted to Hash you should easily convert it to CSV.

xpath issue with selectSingleNode when switch to XML 6

This is my XML:
<?xml version="1.0"?>
<Revision>
<Revision Index="1"/>
</Revision>
When using DomDocument(ver 3) I could run the following(In VB6):
Set objNode = objDom.documentElement.selectSingleNode("//.[#Index = '1']")
This is to identify that this attribute exists with it's value.
Now after moving to DomDocument60(ver 6) this line fails.
How should I re-write it so it works with DomDocument60?
Thanks in advance
Doron
You could try using the XPath:
//Revision[#Index="1"]
This will select all Revision nodes in the document that have the attribute Index="1".

How to extract xml attributes using Xpath in Pig?

I wanted to extract the attributes form an xml using Pig Latin.
This is a sample of the xml file
<CATALOG>
<BOOK>
<TITLE test="test1">Hadoop Defnitive Guide</TITLE>
<AUTHOR>Tom White</AUTHOR>
<COUNTRY>US</COUNTRY>
<COMPANY>CLOUDERA</COMPANY>
<PRICE>24.90</PRICE>
<YEAR>2012</YEAR>
</BOOK>
</CATALOG>
I used this script but it didn't work:
REGISTER ./piggybank.jar
DEFINE XPath org.apache.pig.piggybank.evaluation.xml.XPath();
A = LOAD './books.xml' using org.apache.pig.piggybank.storage.XMLLoader('BOOK') as (x:chararray);
B = FOREACH A GENERATE XPath(x, 'BOOK/TITLE/#test'), XPath(x, 'BOOK/PRICE');
dump B;
The output was:
(,24.90)
I hope someone can help me with this.
Thanks.
There are 2 bugs in piggybank's XPath class:
The ignoreNamespace logic breaks searching for XML attributes
https://issues.apache.org/jira/browse/PIG-4751
The ignoreNamepace parameter is defaulted to true and cannot be overwritten
https://issues.apache.org/jira/browse/PIG-4752
Here is my workaround using XPathAll:
XPathAll(x, 'BOOK/TITLE/#test', true, false).$0 as (test:chararray)
Also if you still need to ignore namespaces:
XPathAll(x, '//*[local-name()=\'BOOK\']//*[local-name()=\'TITLE\']/#test', true, false).$0 as (test:chararray)

eXist db index not used in xquery

I have stored in my eXist db nodes of the following type:
<Order ID="170473" LnkID="8288374995" OrignDt="2003-07-08" TrdDt="2003-07-09" Acct="104158163" AcctIDSrc="99" DayBkngInst="ingrated" BkngUnit="hobbyhorse" SettlDt="2003-07-28" ClrFeeInd="B" HandlInst="3" MinQty="2088.58" ProcCode="1" Side="2"
LocReqd="N" TxnTm="2003-07-06T08:44:24" QtyTyp="0" Typ="A" PxTyp="4" Px="4258.33" Ccy="USD" SolFlag="N" IOIID="8596226323" ExpireDt="2003-06-19" GTBkngInst="2" Cpcty="A" Rstctions="A" CustCpcty="1660" ForexReq="Y" SettlCcy="inclination" Txt="eats" EncTxt="pendulous" Qty2="4028.86" MaxShow="1636.80" CxllationRights="M" MnyLaunderingStat="N" Designation="tied" >
<Hdr SID="997453497" D2ID="5969180787" SSub="swiftest" D2Sub="flay" PosDup="N" Snt="2003-10-24T12:13:50" OrigSnt="2003-07-19T00:23:46" MsgEncd="lechery" ><Hop ID="9148044310" Ref="33787" Snt="2003-08-24T21:26:11"></Hop>
</Hdr><Pty ID="8059449011" Src="H" ><Sub ID="228" ></Sub></Pty>
<Instrmt Sym="VRTS" Sfx="CD" ID="8962619773" Src="5" CFI="entrances" MatDt="2003-12-09" CpnPmt="2004-06-12" Issued="2004-05-14" RepoTrm="2749" CrdRtg="dad" IssuCtry="purpose" Redeem="2003-10-17" Strk="2028.23" StrkCcy="posterns" Exch="religiously" EncSecDescLen="4238" Pool="separation" IntAcrl="2003-08-17" ></Instrmt>
<OrdQty Qty="3652" Cash="3036.44" Pct="3882.34" RndDir="2" RndMod="1819.70" ></OrdQty>
</Order>
I would like to have an index for the ID attribute. My configuration file is:
<collection xmlns="http://exist-db.org/collection-config/1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<index>
<create qname="#ID" type="xs:string"/>
</index>
<triggers>
<trigger class="org.exist.extensions.exquery.restxq.impl.RestXqTrigger"/>
</triggers>
The index I have created is only used in pure xpath queries, such as
//Order[#ID ="170475"]
but not in xquery queries such as:
for $ord in//Order/#ID
where $ord = "150985"
return $ord
Is there any way to fix this?
Please try to change your query into
for $ord in//Order
where $ord/#ID = "150985"
return $ord
The query engine tries to rewrite your expression in order to use the index. It will fail analyzing your previous formulation, but should succeed on the one above.
The general recommendation is to use XPath statements with filters where possible, because they are easier to rewrite automatically.
It is documented that the eXist-db xquery processor has difficulties to optimize queries with the where clause.
Although your second query is syntactically correct, it is recommended to use the XPATH equivalent.

Resources