Why not working canonicalizer XML in nojejs xml-c14n - php

I have problem in XML, when I need that a element child contain Parent's attributes in Nodejs. Now only atribute show in child canonicalized is xmlns, but, for instance, there are attributes xmlns:ns1, xmlns:types, the attributes don't in child element after function canonicalize.
I cant't to search function/lib in Node, make this for me.
In PHP I can do this, with function C14N.
In PHP i have :
Input :
$xml = '<?xml version="1.0" encoding="UTF-8"?>
<ns1:SendTest xmlns:ns1="http://localhost:8080/TestA/a" xmlns:type="http://localhost:8080/TestA/b" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://localhost:8080/TestA/a http://localhost:8080/TestA/xsd/SendTest.xsd">
<HEAD>
<TESTA>6291</TESTA>
</HEAD>
<TESTB Id="testeb:1ABCDZ">
<TESTC>
<TESTD>e4c47c91392cd57088c28468be0ef2349782f2df</TESTD>
</TESTC>
</TESTB>
</ns1:SendTest>';
PHP Code:
$d = new DOMDocument('1.0');
$d->loadXML($xml);
$data = $d->getElementsByTagName('TESTB')->item(0)->C14N(FALSE,FALSE,NULL,NULL);
echo ($data);
die();
OUTPUT :
<?xml version="1.0" encoding="UTF-8"?>
<TESTB xmlns:ns1="http://localhost:8080/TestA/a" xmlns:type="http://localhost:8080/TestA/b" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Id="testeb:1ABCDZ">
<TESTC>
<TESTD>e4c47c91392cd57088c28468be0ef2349782f2df</TESTD>
</TESTC>
</TESTB>
not Working in NodeJs (xml-c14n) :
const c14n = require("xml-c14n")();
const DOMParser = require("xmldom").DOMParser;
async function test (){
let xml = xml(input PHP);
let doc = (new DOMParser()).parseFromString(xml);
let canonicalizer = c14n.createCanonicaliser("http://www.w3.org/2001/10/xml-exc-c14n#");
let lote = doc.getElementsByTagName('TESTB');
let canonicalized = await canonicalizer.canonicalise(lote[0]);
console.log(canonicalized.toString());
}
test();
output :
<TESTB Id="testeb:1ABCDZ">
<TESTC>
<TESTD>e4c47c91392cd57088c28468be0ef2349782f2df</TESTD>
</TESTC>
</TESTB>
The result I get is not correct,suggestion for my question?

Related

PHP SOAP Server response in XML format

I'm creating SOAP web service using PHP.
Here is my code..
SoapServer.php
class server{
public function RegisterComplaint($strInputXml){
$str = "<RESULT><complaintNo>09865678</complaintNo></RESULT>";
$arr['RegisterComplaintResult'] = trim($str);
return $arr;
}
}
$custom_wsdl = 'custom.wsdl';
$server = new SoapServer($custom_wsdl);
$server->setClass('server');
$server->handle();
When I call RegisterComplaint using Wizdler(chrome extension) I get below result:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.Insurer.com/webservices/">
<SOAP-ENV:Body>
<ns1:RegisterComplaintResponse>
<ns1:RegisterComplaintResult><RESULT><complaintNo>09865678</complaintNo></RESULT></ns1:RegisterComplaintResult>
</ns1:RegisterComplaintResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Here I want result in below format(special characters to HTML entities):
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.Insurer.com/webservices/">
<SOAP-ENV:Body>
<ns1:RegisterComplaintResponse>
<ns1:RegisterComplaintResult><RESULT><complaintNo>09865678</complaintNo></RESULT></ns1:RegisterComplaintResult>
</ns1:RegisterComplaintResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Does any one know what I have to change for required output?
I tried html_entity_decode() & htmlspecialchars() on $str variable, but it's not working.
The solution as response. (Already quoted out in the comments)
The SoapServer class awaits an object as return value. This object will be automatically encoded by the server using the definitions from the used wsdl file. If a string is returned, its entities will always be encoded.
class Server
{
public function registerComplaint()
{
$registerComplaintResponse = new stdClass();
$registerComplaintResult = new stdClass();
$result = new \stdClass();
$result->complaintNo = '09865678';
$registerComplaintResult->RESULT = $result;
$registerComplaintResponse->RegisterComplaintResult = $registerComplaintResult;
return $registerComplaintResponse;
}
}
All definitions of return types (complex types) are defined in the wsdl file.

Load the xml in php and return the data

i'm looking how to Load the XML file in PHP and Return the data not redirect. Preferably to hide the xml content from the end user as much as i can.
I've seen something like this, but i can not make it work, please if you can write out the complete code with a link example..
public function sendResponse($type,$cause) {
$response = '<?xml version="1.0" encoding="utf-8"?>';
$response .= '<response><status>'.$type.'</status>';
$response = $response.'<remarks>'.$cause.'</remarks></response>';
return $response;
}
....
....
header("Content-type: text/xml; charset=utf-8");
echo sendResponse($type,$cause);
Please help if you can.
Thank's in Advance,
SX
I'm not sure to understand your request, but first you can't call sendResponse() cause it's not a function but a method in a Class
You need to instantiate your class and after, call the method.
Example :
$yourObject = new YourClass();
$yourObject->sendResponse();
See the manual
For your case, see the manual for simpleXML and try that :
function sendResponse($type,$cause) {
$response = '<?xml version="1.0" encoding="utf-8"?>';
$response .= '<response><status>'.$type.'</status>';
$response = $response.'<remarks>'.$cause.'</remarks></response>';
return $response;
}
$type="type";
$cause="cause";
var_dump(simplexml_load_string(sendResponse($type,$cause)));
If your script is external, you can get it with file_get_contents
$xml = file_get_contents('http://yourTarget.com');
var_dump($xml);
You question misleads me to some extent, make sure if you want to load an external xml file and make your PHP code parse it. Try the following code
Assume the following is your xml content fo text.xml
<?xml version='1.0' encoding='UTF-8'?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>"
<-- PHP -->
$file = 'http://exmp.com/text.xml'; // give the path of the external xml file
if(!$xml = simplexml_load_file($file)) // this checks whether the file exists
exit('Failed to open '.$file); // exit when the path is wrong
print_r($xml); // prints the xml format in the form of array
your output will be this
SimpleXMLElement Object (
[to] => Tove
[from] => Jani
[heading] => Reminder
[body] => Dont forget me this weekend!
)
Hope this helps...

XML signature differences between HEREDOC and DOMDocument

An API client I have developed works with XML messages and the messages are signed according to the XML Signature Syntax and Processing specification. After a long struggle, I finally got the signatures working.
At this moment I am building the XML with HEREDOC (simply php strings) and with a cleanup, I'd like to create the XML with DOMDocument directly. However, this causes the message to be invalidated by the server.
This is the current setup (server accepts this message when signed):
$xml = <<<EOT
<?xml version="1.0" encoding="UTF-8"?>
<DirectoryReq xmlns="http://www.idealdesk.com/ideal/messages/mer-acq/3.3.1" version="3.3.1">
<createDateTimestamp>$timestamp</createDateTimestamp>
<Merchant>
<merchantID>$merchantId</merchantID>
<subID>$subId</subID>
</Merchant>
</DirectoryReq>
EOT;
$document = new DOMDocument();
$document->loadXML($xml);
This is the OO approach (server rejects this message when signed):
$document = new DOMDocument('1.0', 'UTF-8');
$request = $document->createElement('DirectoryReq');
$xmlns = $document->createAttribute('xmlns');
$xmlns->value = 'http://www.idealdesk.com/ideal/messages/mer-acq/3.3.1';
$version = $document->createAttribute('version');
$version->value = '3.3.1';
$request->appendChild($xmlns);
$request->appendChild($version);
$merchant = $document->createElement('Merchant');
$merchant->appendChild($document->createElement('merchantID', $merchantId));
$merchant->appendChild($document->createElement('subID', $subId));
$request->appendChild($document->createElement('createDateTimestamp', $timestamp));
$request->appendChild($merchant);
$document->appendChild($request);
What can cause the difference as such the XML signature is invalidated by the server? The code to sign the message is exactly the same. The server is simply reporting "Invalid electronic signature".
If required I can show more code.
EDIT, more output and comparison of XML generated
To give some more information, this is the output of the first (HEREDOC) xml, generated via $document->saveXml():
<?xml version="1.0" encoding="UTF-8"?>
<DirectoryReq xmlns="http://www.idealdesk.com/ideal/messages/mer-acq/3.3.1" version="3.3.1">
<createDateTimestamp>2013-08-10T19:41:20.000Z</createDateTimestamp>
<Merchant>
<merchantID>0020XXXXXX</merchantID>
<subID>0</subID>
</Merchant>
</DirectoryReq>
This is the output ($document->saveXML()) for the second (direct DOMDocument generation) method:
<?xml version="1.0" encoding="UTF-8"?>
<DirectoryReq xmlns="http://www.idealdesk.com/ideal/messages/mer-acq/3.3.1" version="3.3.1">
<createDateTimestamp>2013-08-10T19:41:20.000Z</createDateTimestamp>
<Merchant>
<merchantID>0020XXXXXX</merchantID>
<subID>0</subID>
</Merchant>
</DirectoryReq>
In php, var_dump() gives the exact same string length. If I compare both strings (=== obviously) they are the same. Comparing both objects, then they are not the same.
Signing example
Signing occurs with the library xmlseclibs with this code (NB. both types are signed the same way!):
public function sign(DOMDocument $document, $fingerprint, $keyfile, $passphrase = null)
{
$dsig = new XMLSecurityDSig();
$dsig->setCanonicalMethod(XMLSecurityDSig::EXC_C14N);
$dsig->addReference($document, XMLSecurityDSig::SHA256,
array('http://www.w3.org/2000/09/xmldsig#enveloped-signature'),
array('force_uri' => true)
);
$key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, array('type' => 'private'));
if ($passphrase !== null) {
$key->passphrase = $passphrase;
}
$key->loadKey($keyfile, true);
$dsig->sign($key);
$dsig->addKeyInfoAndName($fingerprint);
$dsig->appendSignature($document->documentElement);
}
If I dump the XML after it's signed, the <DigestValue> and <SignatureValue> values are different. So the server is correct the signature is invalid, but I cannot come up with a clue why method A works and B not.
You are overwriting $merchant when you create the Merchant element, so just rename the variable
$merchantElement = $document->createElement('Merchant');
I have now solved it by exporting and importing the XML again. It's quite ugly, but allows me to flexibly handle the DOMNodes.
protected function repairDOMDocument(DOMDocument $document)
{
$xml = $document->saveXML();
$document = new DOMDocument;
$document->loadXML($xml);
return $document;
}
If there is a suggestion how to stop doing this, I am pleased to hear so.

SimpleXML insert Processing Instruction (Stylesheet)

I want to integrate an XSL file in an XML string gived me by php CURL command.
I tryed this
$output = XML gived me by curl option;
$hotel = simplexml_load_string($output);
$hotel->addAttribute('?xml-stylesheet type=”text/xsl” href=”css/stile.xsl”?');
echo $hotel->asXML();
Doing this when I see the XML on browser, I receive the file without the stylesheet.
Where is my error?
A SimpleXMLElement does not allow you by default to create and add a Processing Instruction (PI) to a node. However the sister library DOMDocument allows this. You can marry the two by extending from SimpleXMLElement and create a function to provide that feature:
class MySimpleXMLElement extends SimpleXMLElement
{
public function addProcessingInstruction($target, $data = NULL) {
$node = dom_import_simplexml($this);
$pi = $node->ownerDocument->createProcessingInstruction($target, $data);
$result = $node->appendChild($pi);
return $this;
}
}
This then is easy to use:
$output = '<hotel/>';
$hotel = simplexml_load_string($output, 'MySimpleXMLElement');
$hotel->addProcessingInstruction('xml-stylesheet', 'type="text/xsl" href="style.xsl"');
$hotel->asXML('php://output');
Exemplary output (beautified):
<?xml version="1.0"?>
<hotel>
<?xml-stylesheet type="text/xsl" href="style.xsl"?>
</hotel>
Another way is to insert an XML chunk to a simplexml element: "PHP SimpleXML: insert node at certain position" or "Insert XML into a SimpleXMLElement".

Building an xml document from functions that return DOMNodes

My question is a rather simple one for anyone familiar with the DOM* classes in PHP.
Basically i have different classes that i want to return to me something that I can append in my xml document
Following pseudo-code should demonstrate better
Class ChildObject{ function exportToXML( return a DOMNode ? ) }
Class ContainerObject{
function exportToXML(){
$domSomething = new DOM*SOMETHING*;
foreach($children as $child) $domSomething->appendChild($child->exportToXML);
return $domSomething ;
}
}
Now i want to create the entire DOMDocument
$xml = new DOMDocument();
$root = $xml->createElement('root');
foreach($containers as $container) $root->appendChild($container->exportToXML());
I tried sending the DOMDocument object as a reference, did not work. I tried creating DOMNodes but didn't work as well....so i'm looking at a simple answer: what datatypes do i need to return in order for me to achieve the above functionality?
<?php
$xml = new DOMDocument();
$h = $xml->createElement('hello');
$node1 = new DOMNode('aaa');
$node1->appendChild(new DOMText('new text content'));
//node1 is being returned by a function
$node2 = new DOMNode('bbb');
$node2->appendChild(new DOMText('new text content'));
//node2 is being returned by some other function
$h->appendChild($node1);//append to this element the returned node1
$h->appendChild($node2);//append to this element the returned node2
$xml->appendChild($h);//append to the document the root node
$content = $xml->saveXML();
file_put_contents('xml.xml', $content);//output to an xml file
?>
The above code should do the following:
consider that i want to build the following xml
<hello>
<node1>aaa</node1>
<node2>bbb</node2>
</hello>
node1 could be again a node that has multiple children so node1 could be as well as something like this:
<node1>
<child1>text</child1>
<child2>text</child2>
<child3>
<subchild1>text</subchild1>
</child3>
</node1>
Basically when i call exportToXML() something should be returned, call it $x that i can append in my document using $xml->appendChild($x);
I want to create the above structure and return the object that can be appended in the DOMDocument
The following code:
<?php
$xml = new DOMDocument();
$h = $xml->appendChild($xml->createElement('hello'));
$node1 = $h->appendChild($xml->createElement('aaa'));
$node1->appendChild($xml->createTextNode('new text content'));
$node2 = $h->appendChild($xml->createElement('bbb'));
$node2->appendChild($xml->createTextNode('new text content'));
$xml->save("xml.xml");
?>
will produce:
<?xml version="1.0"?>
<hello>
<aaa>new text content</aaa>
<bbb>new text content</bbb>
</hello>
Your example XML showed <node1>aaa</node1> but I think your various code snippet examples went out of sync when you were editing =) In case you need that output, try:
<?php
$xml = new DOMDocument();
$h = $xml->appendChild($xml->createElement('hello'));
$node1 = $h->appendChild($xml->createElement('node1'));
$node1->appendChild($xml->createTextNode('aaa'));
$node2 = $h->appendChild($xml->createElement('node2'));
$node2->appendChild($xml->createTextNode('bbb'));
$xml->save("xml.xml");
?>

Categories