using simple XML (php to change one attribute) - php

I have an xml input in the form of a string and I want to look at it and find a particular element and modify it.
The part of the xml input I'm interested in looks like this and is part of the hierarchy of the in the string
<com:GTe Type="GTe" xmlns:com="http://xyx.com/Gte">
<com:Cd ED="2021-07" Number="0123456789"/>
</com:GTe>
the ED element varies so im only interested in identifying all of the com:Cd children where it has a Number Attribute and then changing all but the last three digits of the number attribute to another string.
The project uses Symfony and simple XML php but I'm not sure how to do this as other parts of the xml use the Number key for other data.
Tried the following
$message =
'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<uv:HCRReq
<com:GTe Type="GTe" xmlns:com="http://xyx.com/Gte">
<com:Cd ED="2021-07" Number="0123456789"/>
</com:GTe>
</uv:HCRReq>
</soapenv:Body>
</soapenv:Envelope>';
$xmlstring = simplexml_load_string($message);
//currently not working
$number = $xmlstring->soapenv:Envelope->soapenv:Body->uv:HCRReq->com:GTe->com:CD->number;
$length = strlen($number);
//need to check length is 11 or 12 long
$alteredNum = '1234567'.substr($number,length-3,3);
// Not sure how to set the string

Can you try this:
$message =
'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<uv:HCRReq>
<com:GTe Type="GTe" xmlns:com="http://xyx.com/a">
<com:Cd ED="2021-07" Number="012345678999"/>
</com:GTe>
</uv:HCRReq>
</soapenv:Body>
</soapenv:Envelope>';
$xml = simplexml_load_string($message);
$nodes = $xml->xpath('//*[name()="com:Cd" and #Number]');
if ($nodes) {
$number = (string)$nodes[0]->attributes()['Number'];
if (12 === strlen($number) || 11 === strlen($number)) {
unset($nodes[0]->attributes()['Number']);
$nodes[0]->addAttribute('Number', '111' . substr($number, -3, 3));
}
}
print_r($xml->asXML());
Result:
<?xml version="1.0"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<uv:HCRReq>
<com:GTe xmlns:com="http://xyx.com/a" Type="GTe">
<com:Cd ED="2021-07" Number="111999"/>
</com:GTe>
</uv:HCRReq>
</soapenv:Body>
</soapenv:Envelope>
Although it seems the <uv:HCRReq xml start tag is missing the> but that might have been a copy paste issue.

Related

Read XML data from string [duplicate]

This question already has answers here:
Reference - How do I handle Namespaces (Tags and Attributes with a Colon in their Name) in SimpleXML?
(2 answers)
Closed 2 years ago.
now i need to ask this, have this XML:
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://webservice.telemetry.udo.fors.ru/" 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">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1">
<wsse:UsernameToken>
<wsse:Username/>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"/>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<web:storeTelemetryList xmlns="http://webservice.telemetry.udo.fors.ru/">
<telemetryWithDetails xmlns="">
<telemetry>
<coordX>-108.345268</coordX>
<coordY>25.511797</coordY>
<date>2020-04-16T16:48:07Z</date><glonass>0</glonass>
<gpsCode>459971</gpsCode>
<speed>0</speed>
</telemetry>
</telemetryWithDetails>
</web:storeTelemetryList>
</soapenv:Body>
</soapenv:Envelope>
and im using simplexml on PHP to read it but i get the error "Trying to get property 'telemetryWithDetails' of non-object" when i try to get the data in coordx, coordy,date, gpscode and speed node but i cant get there here is my code:
$string = <<<XML
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope...(same from above)
XML;
$xml = new SimpleXMLElement($string);
echo $xml->Body->storeTelemetryList->telemetryWithDetails;
if i put "->telemetryWithDetails->telemetry->coordX" i get "Trying to get property 'telemetry' of non-object, Trying to get property 'coordX' of non-object" and the same if use "simplexml_load_string" Hope you can help me thanks
A simple solution is to use XPath and describe the "path" to the values you want :
$xml = simplexml_load_string($xmlstring);
$telemetries = $xml->xpath('/soapenv:Envelope/soapenv:Body/web:storeTelemetryList/telemetryWithDetails/telemetry');
$telemetry = $telemetries[0] ;
$coordX = (string) $telemetry->xpath('./coordX')[0] ;
$coordY = (string) $telemetry->xpath('./coordY')[0] ;
echo $coordX ; //-108.345268
echo $coordY ; // 25.511797
XPath returns always a collection, so select the first node with [0]. The (string) conversion is used to extract the text value inside the node.

PHP get data from multilevel tag colon XML file DOM PHP

I have question , how to parsing data from multilevel tag colon XML file with dom PHP.
Below is my XML sample data. I want to get data inside < transfer > and return as an array data
<soapenv:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<HostCustomerResponse xmlns="http://xx.xx.xx.xx">
<ns1:output xmlns:ns1="http://xx.xx.xx" xmlns:ns2="some:url" xsi:type="ns2:Output">
<ns2:statusCode>00</ns2:statusCode>
<ns2:statusMsg/>
<ns2:txnResponseDateTime>20190625164236</ns2:txnResponseDateTime>
<ns2:txnData>
<transferRequest>
<transfer>
<transferId>123456789</transferId>
<txnDate>123456789</txnDate>
<debitAcctNo>123456789</debitAcctNo>
<benAcctNo>123456789</benAcctNo>
</transfer>
</transferRequest>
</ns2:txnData>
</ns1:output>
</HostCustomerResponse>
</soapenv:Body>
</soapenv:Envelope>
and this result i want.
array(
[transferID] => 123456789,
[txnDate] => 123456789,
.....
)
Not sure if http://xx.xx.xx.xx is the real namespace in
<HostCustomerResponse xmlns="http://xx.xx.xx.xx">
but as this defines the namespace for any default elements (i.e. the ones your after) then you need to load the source XML and then register this namespace. Then you can use XPath to find the <transfer> element. You then just iterate through the elements within that ( using children() and add them into the output array...
$xml = simplexml_load_string($source);
$xml->registerXPathNamespace("d", "http://xx.xx.xx.xx");
$transfer = $xml->xpath("//d:transfer")[0];
$output = [];
foreach ( $transfer->children() as $key=> $value ) {
$output[$key] = (string)$value;
}
Your original XML is missing the definition of the soapenv namespace, so I added that to make the XML correct...
<soapenv:Envelope xmlns:soapenv="http://soapev.com"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<HostCustomerResponse xmlns="http://xx.xx.xx.xx">
<ns1:output xmlns:ns1="http://xx.xx.xx" xmlns:ns2="some:url" xsi:type="ns2:Output">
<ns2:statusCode>00</ns2:statusCode>
<ns2:statusMsg/>
<ns2:txnResponseDateTime>20190625164236</ns2:txnResponseDateTime>
<ns2:txnData>
<transferRequest>
<transfer>
<transferId>123456789</transferId>
<txnDate>123456789</txnDate>
<debitAcctNo>123456789</debitAcctNo>
<benAcctNo>123456789</benAcctNo>
</transfer>
</transferRequest>
</ns2:txnData>
</ns1:output>
</HostCustomerResponse>
</soapenv:Body>
</soapenv:Envelope>
You can get the transfer node by using the following code snippet
$response = preg_replace("/(<\/?)(\w+):([^>]*>)/", "$1$2$3", $soapXMLResult);
$xml = new SimpleXMLElement($response);
$body = $xml->xpath('//soapenvBody')[0];
$array = json_decode(json_encode((array)$body), TRUE);
$transfer = $array['HostCustomerResponse']['ns1output']['ns2txnData']['transferRequest']['transfer'];
https://3v4l.org/UKnZs

How i can get sessionid from this SOAPXML

I want to get sessionid from this XML piece of code:
<soapenv:envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:header>
<soapenv:body>
<p725:loginresponse xmlns:p725="http://www.fleetboard.com/data">
<p725:loginresponse sessionid="0001nABbah-I8f75oDrVbHrBgOv:s96fb0a4m3"></p725:loginresponse>
</p725:loginresponse>
</soapenv:body>
</soapenv:header>
</soapenv:envelope>
I have tried this but this doesn't work:
$soap=simplexml_load_string($result);
$xml_response = $soap->children('http://schemas.xmlsoap.org/soap/envelope/')->Body()->children()->p725;
echo $session_id = (int) $xml_response->session_id;
There are two ways to do this. The first is as you are currently doing it, but this involves various changes of namespace and means you need to keep on getting the right child elements and the attribute itself...
$soap=simplexml_load_string($result);
$xml_response = $soap->children("http://schemas.xmlsoap.org/soap/envelope/")->header->body;
$session_id = $xml_response->children("http://www.fleetboard.com/data")->loginresponse->loginresponse;
echo $session_id->attributes()->sessionid.PHP_EOL;
Or you can use XPath, where you will need to register the namespace with the document first and then select the loginresponse element with a sessionid element. This will return a list of matches, so you have to take the first one using [0]...
$soap=simplexml_load_string($result);
$soap->registerXPathNamespace("p725", "http://www.fleetboard.com/data");
$session_id = $soap->xpath("//p725:loginresponse/#sessionid");
echo $session_id[0];

Parse SOAP with namespaces using php

I am trying to parse the following SOAP using PHP. I have tried every possible solution found in here but I did not manage it due to the namespaces used. Can please someone help?
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:geo="http://path.to.geo" xmlns:geo1="http://path/">
<soapenv:Header/>
<soapenv:Body>
<geo:SendClient>
<geo1:SendClientRequest>
<geo1:GeneralInfo>
<geo1:Team>AP</geo1:Team>
</geo1:GeneralInfo>
</geo1:SendClientRequest>
</geo:SendClient>
</soapenv:Body>
</soapenv:Envelope>
I want to get the value AP in the Output.
$xmlData = simplexml_load_file('request.xml');
$xmlData->registerXPathNamespace('geo1', 'http://path/');
foreach ($xmlData->xpath('//geo1:GeneralInfo') as $item)
{
print_r($item);
var_export($item->xpath('//geo1:Team'));
}
After spending hours I found out that the right way to print the output is:
$result = $item->xpath('//geo1:Team');
echo (string)$result[0];
instead of
var_export($item->xpath('//geo1:Team'));

Parse soap xml document php

I have this SOAP response.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<pkup:PickupPendingStatusResponse xmlns:pkup="http://www.ups.com/XMLSchema/XOLTWS/Pickup/v1.1">
<common:Response xmlns:common="http://www.ups.com/XMLSchema/XOLTWS/Common/v1.0">
<common:ResponseStatus>
<common:Code>1</common:Code>
<common:Description>Success</common:Description>
</common:ResponseStatus>
</common:Response>
<pkup:PendingStatus>
<pkup:PickupType>01</pkup:PickupType>
<pkup:ServiceDate>20141006</pkup:ServiceDate>
<pkup:PRN>2929AONCALL</pkup:PRN>
<pkup:OnCallStatusCode>001</pkup:OnCallStatusCode>
<pkup:PickupStatusMessage>Received at dispatch</pkup:PickupStatusMessage>
<pkup:BillingCode>01</pkup:BillingCode>
<pkup:ContactName>Shipping Mgr.</pkup:ContactName>
<pkup:ReferenceNumber>OnCallNextDayAir</pkup:ReferenceNumber>
</pkup:PendingStatus>
</pkup:PickupPendingStatusResponse>
</soapenv:Body>
I need to get the PickupPendingStatusResponse->Response->ResponseStatus->Description.
I also would like to get pkup:PendingStatus into an array and be able to get each of it's children values.
I used the DOMDocument class to get the nodes
$doc = new DOMDocument();
$doc->loadXML($upsResponse);
$PRN = $doc->getElementsByTagName('PRN')->item(0)->nodeValue;
$success = $doc->getElementsByTagName('Description')->item(0)->nodeValue;

Categories