Cannot use XPATH to get a value from SOAP response - xpath

Please help me to get value (013b92124ce54924) in "<web:prop value='013b92124ce54924' name='serviceId'></web:prop>"
I tried to use the xpath command unsuccessful:
/*/SOAP-ENV:Body/'ns':requestResponse/web:webapiResponse/web:data/web:prop[#name='serviceId']/#value
My SOAP response is as below:
`
<?xml version="1.0" encoding="utf-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Body>
<ns:requestResponse xmlns:ns='http://www.phahahotel.com/BPS/sWebAPI'>
<web:webapiResponse xmlns:web='http://www.phahahotel.com/BPS/WebService' action='CreateServiceTel' transId='10100000009' clientId='svrcore'>
<web:respCode>0000</web:respCode>
<web:respDescription>Success</web:respDescription>
<web:data>
<web:prop value='SERTYPE' name='serviceType'></web:prop>
<web:prop value='013b92124ce54924' name='serviceId'></web:prop>
</web:data>
</web:webapiResponse>
</ns:requestResponse>
</SOAP-ENV:Body>
`
Thanks,

Remove the quotes around ns :-
% xpath test.xml "/*/SOAP-ENV:Body/ns:requestResponse/web:webapiResponse/web:data/web:prop[#name='serviceId']/#value"
Found 1 nodes:
-- NODE --
value="013b92124ce54924"

Related

Read value from XML within another XML: Mule

I am making a SOAP webservice call and I get the below response. I want to read the value in internal XML, the value is 12345684 in 1234684 in the below XML.
I was able to get internal XML using #[xpath3('//:processaResponse /return[2]')], store it in a flow variable and #[xpath3('/AckReg/DataArea/PRegistration/PRDet/Person/IDSet/:ID[#schemeName="aid"]/text()')].
This works when I try an online parser, but it doesn't read the value in Mule.
Is there any way to extract 1234684 in oa:ID tag using one XPath.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<ns3:TXID xmlns:ns3="http://a.d.r.test.com/"></ns3:TXID>
<ns3:SESSIONID xmlns:ns3="http://a.d.r.test.com/"></ns3:SESSIONID>
</soapenv:Header>
<soapenv:Body>
<ns3:processaResponse xmlns:ns3="http://a.d.r.test.com/" xmlns:ns2="http://p.r.test.com/">
<return>Hi</return>
<return>
<?xml version="1.0" encoding="UTF-8"?>
<AckReg
xmlns="http://www.test.com/e/1" languageCode="en-US" releaseID="normalizedString" systemEnvironmentCode="test" versionID="normalizedString"
xmlns:oa="www.test.com/r/9"
xsi:schemaLocation="http://www.test.com/a/1 ../test/test.xsd">
<Apa>
<oa:CreationDateTime>2018-04-05</oa:CreationDateTime>
</Apa>
<DataArea>
<Ack>
<OArea>
<o:Sender>
<o:LID schemeAgencyName="testi" schemeName="Application ID">test</o:LID>
</o:Sender>
</OArea>
<OriginalActionVerb/>
</Ack>
<PRegistration>
<testids>
<IDSet schemeAgencyName="try">
<oa:ID schemeName="abcid">1234684</oa:ID>
</IDSet>
</testids>
<PRDet>
<Person>
<IDSet schemeAgencyName="try">
<oa:ID schemeName="aid">1364561</oa:ID>
</IDSet>
<IDSet schemeAgencyName="enada">
<oa:ID schemeName="Employee ID">adsad</oa:ID>
</IDSet>
</Person>
<User>
<oa:ID/>
</User>
</PRDet>
</PRegistration>
</DataArea>
</AckReg>
</return>
</ns3:processaResponse>
</soapenv:Body>
</soapenv:Envelope>
In your expressions you were missing namespace prefixes or namespace wildcards *: on some nodes - so your expressions failed.
Is there any way to extract 1234684 in oa:ID tag using one XPath.
Combining both of your partial expressions is possible with namespace wildcards:
//*:processaResponse/return[2]/*:AckReg/*:DataArea/*:PRegistration/*:testids/*:IDSet/*:ID[#schemeName='abcid']/text()
Or you can use an absolute path with namespace wildcards:
/*:Envelope/*:Body/*:processaResponse/return[2]/*:AckReg/*:DataArea/*:PRegistration/*:testids/*:IDSet/*:ID[#schemeName='abcid']/text()
Output in both cases:
1234684
You can even use XmlSlurper class using groovy script to fetch that respective value.
root = new XmlSlurper( false, true).parseText(payload).declareNamespace('soapenv':"http://schemas.xmlsoap.org/soap/envelope/")

Nokogiri parsing through XML fails

The code:
response = Nokogiri::XML(open('https://geocode-maps.yandex.ru/1.x/?geocode=%D0%A1%D0%B0%D0%BD%D0%BA%D1%82-%D0%9F%D0%B5%D1%82%D0%B5%D1%80%D0%B1%D1%83%D1%80%D0%B3+%D0%A1%D0%B2%D0%B5%D1%80%D0%B4%D0%BB%D0%BE%D0%B2%D1%81%D0%BA%D0%B0%D1%8F+%D0%BD%D0%B0%D0%B1%D0%B5%D1%80%D0%B5%D0%B6%D0%BD%D0%B0%D1%8F+44%D0%A2'), nil, Encoding::UTF_8.to_s)
lowerCorner = response.xpath("//lowerCorner")
XML document I parse is like:
<?xml version="1.0" encoding="utf-8"?>
<ymaps xmlns="http://maps.yandex.ru/ymaps/1.x" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://maps.yandex.ru/business/1.x http://maps.yandex.ru/schemas/business/1.x/business.xsd http://maps.yandex.ru/geocoder/1.x http://maps.yandex.ru/schemas/geocoder/1.x/geocoder.xsd http://maps.yandex.ru/psearch/1.x http://maps.yandex.ru/schemas/psearch/1.x/psearch.xsd http://maps.yandex.ru/search/1.x http://maps.yandex.ru/schemas/search/1.x/search.xsd http://maps.yandex.ru/web/1.x http://maps.yandex.ru/schemas/web/1.x/web.xsd http://maps.yandex.ru/search/internal/1.x http://maps.yandex.ru/schemas/search/internal/1.x/internal.xsd">
<GeoObjectCollection>
<metaDataProperty xmlns="http://www.opengis.net/gml">
<GeocoderResponseMetaData xmlns="http://maps.yandex.ru/geocoder/1.x">
<request>Санкт-Петербург Свердловская набережная 44Т</request>
<found>1</found>
<results>10</results>
</GeocoderResponseMetaData>
</metaDataProperty>
<featureMember xmlns="http://www.opengis.net/gml">
<GeoObject xmlns="http://maps.yandex.ru/ymaps/1.x" xmlns:gml="http://www.opengis.net/gml" gml:id="1">
<metaDataProperty xmlns="http://www.opengis.net/gml">
<GeocoderMetaData xmlns="http://maps.yandex.ru/geocoder/1.x">
<kind>house</kind>
<text>Россия, Санкт-Петербург, Свердловская набережная, 44Т</text>
<precision>exact</precision>
</GeocoderMetaData>
</metaDataProperty>
<Envelope>
<lowerCorner>30.397902 59.959183</lowerCorner>
<upperCorner>30.406113 59.9633</upperCorner>
</Envelope>
</boundedBy>
<Point xmlns="http://www.opengis.net/gml">
<pos>30.402008 59.961242</pos>
</Point>
</GeoObject>
</featureMember>
</GeoObjectCollection>
</ymaps>
I'd like to get lowerCorner, but nothing from official and others sources does work:
response.xpath('//lowerCorner')
response.search('//lowerCorner')
response.xpath('xmlns:lowerCorner')
response.xpath('xmlns:lowerCorner', ns).text
response.css('lowerCorner')
The only result is: []
So how to parse lowerCorner's content?
Removing the namespaces (or using them in your path) should help.
Try this:
require "nokogiri"
require "open-uri"
response = Nokogiri::XML(open('https://geocode-maps.yandex.ru/1.x/?geocode=%D0%A1%D0%B0%D0%BD%D0%BA%D1%82-%D0%9F%D0%B5%D1%82%D0%B5%D1%80%D0%B1%D1%83%D1%80%D0%B3+%D0%A1%D0%B2%D0%B5%D1%80%D0%B4%D0%BB%D0%BE%D0%B2%D1%81%D0%BA%D0%B0%D1%8F+%D0%BD%D0%B0%D0%B1%D0%B5%D1%80%D0%B5%D0%B6%D0%BD%D0%B0%D1%8F+44%D0%A2'), nil, Encoding::UTF_8.to_s)
response.remove_namespaces! # <<<<<<<
lower_corner = response.xpath("/ymaps/GeoObjectCollection/featureMember/GeoObject/boundedBy/Envelope/lowerCorner").first
p lower_corner.text #> "30.397902 59.959183"

Reading xml nodes using VB script

I have an xml file that I want to read using VBScript (Technology limitation). Below is the code and xml file. I am able to read the file if there is no DTD element involved but the code doesn't work for file having DTD and xml-style element.
Code-
Dim xmlDoc1:Set xmlDoc1 = CreateObject("MSXML2.DomDocument")
xmlDoc1.async=False
xmlDoc1.load "C:\ABC.xml"
Dim xmlTCID:Set xmlTCID = xmlDoc1.selectNodes("//*")
For nNodeCount = 0 To xmlTCID.length
MsgBox(xmlTCID(nNodeCount).nodeName)
Next
ABC.xml -
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE RESULT SYSTEM "Result.dtd"[]>
<?xml-stylesheet type="text/xsl" href="Result.xsl"?>
<SUMMARY>
<TITLE>Test</TITLE>
</SUMMARY>
<IDS>
<DATA>
<NAME>A</NAME>
<VALUE>PASS</VALUE>
</DATA>
<DATA>
<NAME>B</NAME>
<VALUE>PASS</VALUE>
</DATA
<DATA>
<NAME>C</NAME>
<VALUE>FAIL</VALUE>
</DATA
</IDS>
<IDS>
<DATA>
<NAME>A</NAME>
<VALUE>PASS</VALUE>
</DATA>
<DATA>
<NAME>B</NAME>
<VALUE>FAIL</VALUE>
</DATA
</IDS>
Note - If I avoid -
<!DOCTYPE RESULT SYSTEM "Result.dtd"[]>
<?xml-stylesheet type="text/xsl" href="Result.xsl"?>
The above code is able to read the nodes but with the above two lines in xml file, it gives the below error -
Requirement - I need to read the name of last DATA node with FAIL for each IDS node.
Any suggestion as what to do to get the code working even with -
<!DOCTYPE RESULT SYSTEM "Result.dtd"[]>
<?xml-stylesheet type="text/xsl" href="Result.xsl"?>
As there are problems with your XML - more than one top level element, miising ">" - setting the ProhibitDTD Property to False won't solve all of your tasks.
xmlDoc.validateOnParse=False
worked for me.

Replace all occurrences except the first in Ruby. The regular expression spans multiple lines

I am trying to down my last 3200 tweets in groups of 200(in multiple pages) using restclient gem.
In the process, I end up adding the following lines multiple times to my file:
</statuses>
<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
To get this right(as the XML parsing goes for a toss), after downloading the file, I want to replace all occurrences of the above string except the first.
I am trying the following:
tweets_page = RestClient.get("#{GET_STATUSES_URL}&page=#{page_number}")
message = <<-MSG
</statuses>
<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
MSG
unless page_number == 1
tweets_page.gsub!(message,"")
end
What is wrong in the above? Is there a better way to do the same?
I believe it would be faster to download the whole bunch at once and split the body of your response by message and add it for the first entry.
Something like this, can't try it out so consider this just as an idea.
tweets_page = RestClient.get("#{GET_STATUSES_URL}").body
tweets = tweets_page.split(message)
tweets_page = tweets[0]+message+tweets[1..-1]
You could easily break them up in groups of 200 like that also
If you want to do it with a gsub on the whole text you could use the following
tweets_page = <<-MSG
first
</statuses>
<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
second
</statuses>
<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
rest
MSG
message = <<-MSG
</statuses>
<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
MSG
new_str = tweets_page.gsub message do |match|
if defined? #first
""
else
#first = true
message
end
end
p new_str
gives
type=\"array\">\nrest\n"
"first\n</statuses>\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<statuses type=\"array\">\nsecond\nrest\n"

Get node name with REXML

I have an XML, which can be like
<?xml version="1.0" encoding="utf-8"?>
<testnode type="1">123</testnode>
or like
<?xml version="1.0" encoding="utf-8"?>
<othernode attrib="true">other value</othernode>
or the root node can be something completely unexpected. (Theoretically anything.)
I'm using REXML to parse it. How can I find out what XML node is the root element?
xml = REXML::Document.new "<?xml version" #etc (or load from file)
root_node = xml.elements[1]
root_node_name = root_node.name

Resources