xpath soap namespace grabbing items - soap

I am feeling like i am doing something really not correct.
When doing a soap they return me with an xml which may or may not contain an error.
I would like to check if the error exists if not read the values.
somehow, I can't grab it directly :(
Below is a sample return of something with results and one which gives an error (name not found)
<?xml version="1.0" encoding="utf-8"?>
<soapEnvelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<envHeader xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<wsaAction>http://www.rechtspraak.nl/namespaces/ccr01/searchPersonResponse</wsaAction>
<wsaMessageID>urn:uuid:b75d2932-5687-4871-9d07-3b74b084978a</wsaMessageID>
<wsaRelatesTo>urn:uuid:9112d870-248d-4d07-acd0-d88e4a48d547</wsaRelatesTo>
<wsaTo>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsaTo>
<wsseSecurity>
<wsuTimestamp wsu:Id="Timestamp-061df7b5-32a2-4021-852d-2df98953e076">
<wsuCreated>2011-05-27T12:11:45Z</wsuCreated>
<wsuExpires>2011-05-27T12:16:45Z</wsuExpires>
</wsuTimestamp>
</envHeader>
<soapBody>
<searchPersonResponse xmlns="http://www.rechtspraak.nl/namespaces/ccr01">
<searchPersonResult>
<CCR_WS xmlns="http://www.rechtspraak.nl/namespaces/ccr">
<curandus>
<ccn>1</ccn>
<cur_voornamen>Jan</cur_voornamen>
<cur_voorvoegsels>van</cur_voorvoegsels>
<cur_achternaam>Beek</cur_achternaam>
<geboorte_datum>1980-01-02</geboorte_datum>
<geboorte_plaats>Werkendam</geboorte_plaats>
</curandus>
</CCR_WS>
</searchPersonResult>
</searchPersonResponse>
</soapBody>
</soapEnvelope>
and the one without results
<?xml version="1.0" encoding="utf-8"?>
<soapEnvelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<envHeader xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<wsaAction>http://www.rechtspraak.nl/namespaces/ccr01/searchPersonResponse</wsaAction>
<wsaMessageID>urn:uuid:b75d2932-5687-4871-9d07-3b74b084978a</wsaMessageID>
<wsaRelatesTo>urn:uuid:9112d870-248d-4d07-acd0-d88e4a48d547</wsaRelatesTo>
<wsaTo>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsaTo>
<wsseSecurity>
<wsuTimestamp wsu:Id="Timestamp-061df7b5-32a2-4021-852d-2df98953e076">
<wsuCreated>2011-05-27T12:11:45Z</wsuCreated>
<wsuExpires>2011-05-27T12:16:45Z</wsuExpires>
</wsuTimestamp>
</envHeader>
<soapBody>
<searchPersonResponse xmlns="http://www.rechtspraak.nl/namespaces/ccr01">
<searchPersonResult>
<CCR_WS xmlns="http://www.rechtspraak.nl/namespaces/ccr">
<exceptie errorcode="1">No Results found.</exceptie>
</CCR_WS>
</searchPersonResult>
</searchPersonResponse>
</soapBody>
</soapEnvelope>
Here is my code to select the namespace, then check
$results = simplexml_load_string($response);
$results->registerXPathNamespace('ccr','http://www.rechtspraak.nl/namespaces/ccr');
$lijst = $results->xpath('//ccr:CCR_WS');
$errorcode = $lijst[0]->exceptie->attributes()->errorcode;
$error = $lijst[0]->exceptie;
if (isset($errorcode) AND $errorcode != "") {
// do things with the error code
} else {
$lijst = $results->xpath('//ccr01:searchPersonResult');
$cur = $lijst[0]->CCR_WS->curandus;
echo $cur->ccn."<BR>";
echo $cur->cur_voornamen."<BR>";
echo $cur->cur_voorvoegsels."<BR>";
echo $cur->cur_achternaam."<BR>";
echo $cur->geboorte_datum."<BR>";
echo $cur->geboorte_plaats."<BR>";
}
surely there is a better way of grabbing
$lijst[0]->exceptie->attributes()->errorcode
for example...

...Don't know if this is a "better way" to everyone, but here is a direct XPath expression to select the errorcode. You can make it shorter and less efficient by dropping steps and using // (in the beginning or in the middle). Attributes are selected with # (or with attribute:: axis if you prefer the longer syntax). If attribute (or the exceptie element) doesn't exist, nothing is returned.
/*/*/ccr01:searchPersonResponse/ccr01:searchPersonResult/ccr:CCR_WS/ccr:exceptie/#errorcode
Remember to register all the namespace prefixes that yo use in your XPath expression.

Related

Querying XML data with a long, multi special character, path name

Just getting started with XQuery using BaseX.
The XML structure that I did not create and have no control over, looks like this:
2002test.xml:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:runSearchResponse xmlns:ns2="http://externalapi.business.footprints.numarasoftware.com/">
<return>
<_items>
<_containerDefinitionId>1234</_containerDefinitionId>
<_containerDefinitionName>Service Desk</_containerDefinitionName>
<_itemDefinitionId>2244</_itemDefinitionId>
<_itemDefinitionName>Service Request</_itemDefinitionName>
<_itemId>9989</_itemId>
<_itemFields>
<itemFields>
<fieldName>Icon Name</fieldName>
<fieldValue>
<value>default_ticket.png</value>
</fieldValue>
</itemFields>
<itemFields>
<fieldName>emailCustomerUpdate</fieldName>
<fieldValue>
<value>false</value>
</fieldValue>
</itemFields>
<itemFields>
<fieldName>bestContactNumber_Customer</fieldName>
<fieldValue>
<value/>
</fieldValue>
</itemFields>
</_itemFields>
</_items>
</return>
</ns2:runSearchResponse>
</soap:Body>
</soap:Envelope>
Doing a simple:
for $x in doc("2002test.xml")
return $x
returns my entire document as expected.
Any attempt to drill into it is not working for me however.
I've tried:
for $x in doc("2002test.xml")/soap:Envelope/soap:Body/ns2:runSearchResponse/return
return $x/_items/itemFields/fieldName
But the long path throws a "No namespace declared for 'soap:Envelope'."
So I tried declaring the path like this:
declare variable $m := "/soap:Envelope/soap:Body/ns2:runSearchResponse/return";
for $x in doc("2002test.xml")//$m
return $x
Which got me:
/soap:Envelope/soap:Body/ns2:runSearchResponse/return
/soap:Envelope/soap:Body/ns2:runSearchResponse/return
/soap:Envelope/soap:Body/ns2:runSearchResponse/return
...
I tried:
for $x in doc("2002test.xml")/*[local-name()='soap:Envelope'][local-name()='soap:Body'][local-name()='ns2:runSearchResponse'][local-name()='return']
return $x
Which did nothing.
Very simply I'd like to be able to do something like this:
for $x in doc("2002test.xml")
where $x/return/_items/_itemFields/itemFields/fieldValue/value="default_ticket.png"
return $x/return/_items/_itemFields/itemFields/fieldName/text()
resulting in:
Icon Name
Any advice?
Use basic XPath expressions with a predicate e.g.
doc("2002test.xml")//itemFields[fieldValue/value = "default_ticket.png"]/fieldName/text()
If you think you need a FLOWR expression then use e.g.
for $field in doc("2002test.xml")//itemFields
where $field/fieldValue/value = "default_ticket.png"
return $field/fieldName/text()

Search and get content from data in XML and then place that value in another tag using powershell

Sample text file contains:
`<?xml version="1.0" encoding="UTF-8" ?>
<Document xmlns ="urn:iso:std:iso:20022:tech:xsd:camt.056.001.01"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<FIToFIPmtCxlReq>
<Assgnmt>
<Id>ID123456</Id>
<Assgnr>
<Agt>
<FinInstnId>
<BIC>BICSEND</BIC>
</FinInstnId>
</Agt>
</Assgnr>
<Assgne>
<Agt>
<FinInstnId>
<BIC>BICRCV</BIC>
</FinInstnId>
</Agt>
</Assgne>
<CreDtTm>2020-12-16T09:05:15.0Z</CreDtTm>
</Assgnmt>
<CtrlData>
<NbOfTxs>1</NbOfTxs>
<CtrlSum>0</CtrlSum>
</CtrlData>
<Undrlyg>
<TxInf>
<CxlId>20201216.105.19344855940590400</CxlId>
<OrgnlGrpInf>
<OrgnlMsgId>REF123456789</OrgnlMsgId>
<OrgnlMsgNmId>pacs.008</OrgnlMsgNmId>
</OrgnlGrpInf>
<OrgnlInstrId>FT123456</OrgnlInstrId>
<OrgnlEndToEndId>NOTPROVIDED</OrgnlEndToEndId>
<OrgnlTxId>20201216.100.02202020</OrgnlTxId>
<OrgnlIntrBkSttlmAmt Ccy="EUR">25.23</OrgnlIntrBkSttlmAmt>
<OrgnlIntrBkSttlmDt>2020-12-16</OrgnlIntrBkSttlmDt>`
Please be informed that I would like to code PowerShell to extract the data in tag <OrgnlIntrBkSttlmAmt> (please note that the data length can change since this is an amount field) and then replace the "0" in tag <CtrlSum> with "25.23".
Can someone help me with this.
Thank you for your time.
The xml you show us is invalid as it is missing the following closing tags:
</TxInf>
</Undrlyg>
</FIToFIPmtCxlReq>
</Document>
If I add these, you could do this to update the value in the <CtrlSum> tag:
# load the xml from file
[xml]$xml = Get-Content -Path 'D:\Test\test.xml' -Raw
# get the amount from the 'OrgnlIntrBkSttlmAmt' tag
$amount = $xml.Document.FIToFIPmtCxlReq.Undrlyg.TxInf.OrgnlIntrBkSttlmAmt.'#text'
# use that amount to put in the 'CtrlSum' tag
$xml.Document.FIToFIPmtCxlReq.CtrlData.CtrlSum = $amount
# save the updated xml to file
$xml.Save('D:\Test\test.xml')

PowerShell: XML to Object

I read out data from a XML-File and want to get an object like this:
TaskSequenceNumber TaskSequenceName
------------------ ----------------
1 01_Base
2 02_ABC
The XML-File Looks like this:
$xml = [xml]#"
<?xml version="1.0" encoding="utf-8"?>
<DeploymentScript>
<Settings>
...
</Settings>
<TaskSequences>
<Sequence1>
<TaskSequenceNumber>1</TaskSequenceNumber>
<TaskSequenceName>01_Base</TaskSequenceName>
</Sequence1>
<Sequence2>
<TaskSequenceNumber>2</TaskSequenceNumber>
<TaskSequenceName>02_ABC</TaskSequenceName>
</Sequence2>
</TaskSequences>
</DeploymentScript>
"#
$xml.DeploymentScript.TaskSequences
The code above is prepared for easy copy & paste into ISE, if anybody wants to try it.
About the name of the nodes Sequence1 and Sequence2 I am not sure yet. Maybe they could be renamed to $TaskSequenceName or $TaskSequenceNumber.
.
EDIT:
I am really sorry, but I need to reopen my request about it.
I was trying to implement the posted solution of Martin, but I came into trouble. Look at the following example:
Clear-Host
Function Simple-Test {
Param
(
[Parameter(Mandatory=$true,position=0)]
[string]$ControlObject
)
$ControlObject | Format-Table
}
$xml = [xml]#"
<?xml version="1.0" encoding="utf-8"?>
<DeploymentScript>
<Settings>
...
</Settings>
<TaskSequences>
<Sequence1>
<TaskSequenceNumber>1</TaskSequenceNumber>
<TaskSequenceName>01_Base</TaskSequenceName>
</Sequence1>
<Sequence2>
<TaskSequenceNumber>2</TaskSequenceNumber>
<TaskSequenceName>02_ABC</TaskSequenceName>
</Sequence2>
</TaskSequences>
</DeploymentScript>
"#
Simple-Test -ControlObject $xml.DeploymentScript.TaskSequences.GetEnumerator()
The script won't work as I would expect. I get the result:
System.Xml.XmlElement System.Xml.XmlElement
How to correct this?
Thank you!
You will get the output by calling the GetEnumerator() method:
$xml.DeploymentScript.TaskSequences.GetEnumerator()
Output:
TaskSequenceNumber TaskSequenceName
------------------ ----------------
1 01_Base
2 02_ABC

Perl SOAP::Lite server basics

I'm trying to write a soap server with SOAP::Lite to work with existing soap clients (specifically tr-069 dsl modems), but it's unclear how incoming xml triggers calls. The soap lite mail list moderator is being slow about adding me to their list, so I thought I'd see if anyone here can help point me in the right direction...
For starters, I'm getting:
<faultstring>Unrecognized header has mustUnderstand attribute set to 'true'</faultstring>
which I suspect means that I haven't defined a function to handle something that it wants handled. The handler code (based on the example in the SOAP::Server man page):
SOAP::Transport::HTTP::CGI
->dispatch_to('PeakACS')
->handle;
BEGIN {
package PeakACS;
use vars qw(#ISA);
#ISA = qw(Exporter SOAP::Server::Parameters);
use SOAP::Lite;
my $debugging = 1;
my $console = 0;
my $prog_id = 'peakacs';
my $log = DebugLog->new($prog_id, $debugging, $console);
$log->debug_msg('info', 'handle', '%s', 'handler setup');
sub ID {
$log->debug_msg('info', 'id', '%s', 'got an id');
}
sub Header {
$log->debug_msg('info', 'header', '%s', 'heading');
}
sub Inform {
$log->debug_msg('info', 'inform', '%s', 'informing');
}
}
If I understand SOAP right (which is far from a given), the tag should translate into a call to Inform - the top of the xml request looks like:
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cwmp="urn:dslforum-org:cwmp-1-0">
<SOAP-ENV:Header>
<cwmp:ID SOAP-ENV:mustUnderstand="1">1539095918</cwmp:ID>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<cwmp:Inform>
<DeviceId>
If you want to set mustUnderstand attribute to some entity in Header, do this:
$sheader = SOAP::Header->name('someEntity');
$sheader->mustUnderstand(1);
And when calling a method:
$soap->someMethod($sheader,#request);
Which produces:
<soap:Header>
<someEntity soap:mustUnderstand="1" />
</soap:Header>

How to send XML as String to Soap Action?

I have Soap Action
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<From_Iphone xmlns="http://tempuri.org/">
<MessageText>string</MessageText>
<user_id>int</user_id>
<patientID>int</patientID>
<ReplyToMsgId>int</ReplyToMsgId>
<UserContacts>string</UserContacts>
</From_Iphone>
</soap:Body>
</soap:Envelope>
in this i would like to send the
MessageText =#"Testing";
patientID= 10;
user_id= 20;
ReplyToMsgId=1;
UserContacts = #"< Contacts > < Contact >< id > 5 < /id > < name > Kiran< /name > < gr_id >11 < /gr_id> < /Contact> < Contact>< id>8< /id> < name>najeer< /name>< gr_id>25< /gr_id>< /Contact>< /Contacts>";
I am passing the UserContacts as string but i am not able to hit the server. Please give me a solution for passing an xml as String..
Thank You...
You have to use tag for this.
In tag u have to put Your xmlstring.
The string between the will not be parsed. I think Your problem will be solved.
http://www.w3schools.com/xml/xml_cdata.asp
fallow the above link it will help You