XML decoding Planet request from transaction processor data - PHP Online

Form of PHP Sandbox

Enter Your PHP code here for testing/debugging in the Online PHP Sandbox. As in the usual PHP files, you can also add HTML, but do not forget to add the tag <?php in the places where the PHP script should be executed.

Name: XML decoding Planet request from transaction processor data fullscreencopydownloadembedprint


Your result can be seen below.

Result of php executing





Full code of XML decoding Planet request from transaction processor data.php

  1. <?php
  2.  
  3. $processor_data = <<<EOS
  4. <?xml version="1.0" encoding="UTF-8"?>
  5. <mysql type="array"><auth type="array"><send type="string"><?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header/><soapenv:Body><AuthorizationMCP xmlns="http://www.planetpayment.net"><req><AccessInfo><User>321400000002</User><Password>**************</Password><TerminalID>90000101</TerminalID><ApplicationID>Cardstream v3</ApplicationID><GatewayTransactionId>10017683</GatewayTransactionId></AccessInfo><CardInfo><CardAccountNumber>****************</CardAccountNumber><CardExpirationMonth>12</CardExpirationMonth><CardExpirationYear>19</CardExpirationYear><StartDateMonth>01</StartDateMonth><StartDateYear>19</StartDateYear><CardVerificationNumber>***</CardVerificationNumber><POSEntryMode>010</POSEntryMode><POSConditionCode>59</POSConditionCode><POSTerminalCapability>0</POSTerminalCapability><CardholderIdMethod>4</CardholderIdMethod><ECI>7</ECI><ECIDirectMktgOrderNumber>10017683</ECIDirectMktgOrderNumber><PartialAuthorization>0</PartialAuthorization><TransactionInitiatedBy>2</TransactionInitiatedBy><!-- Not supported<CardVerificationIndicator/><Track1/><Track2/><Track3/><CustomerDataStoreAccessInfo/><BuyVoiceAccessInfo/><RecurringTransaction/><PCard/><AdditionalMarketData/><CardInfoEnv/><BillPayment/><DebitRequest/><InternetAirlineCustomer/><CardType/><InstallmentPayment1/><InstallmentPayment2/>--><FinalAuthIndicator>P</FinalAuthIndicator></CardInfo><TransactionInfo><RequestIdentifier>5d655400b7119</RequestIdentifier><TransactionAmount>780</TransactionAmount><TransactionCurrencyCode>826</TransactionCurrencyCode></TransactionInfo><BillingAndShippingInfo><BillingName>Nick Turner</BillingName><BillingAddress>Flat 6, Primrose Rise347 Lavender Road</BillingAddress><BillingCity>Northampton</BillingCity><BillingState>Northamptonshire</BillingState><BillingPostalCode>NN17 8YG</BillingPostalCode><BillingCountry>GB</BillingCountry><BillingEmail>[email protected]</BillingEmail><ShippingName>Operations Manager</ShippingName><ShippingAddress>3705 Bank of America Tower12 Harcourt Road</ShippingAddress><ShippingCity>Hong Kong</ShippingCity><ShippingState>Central</ShippingState><ShippingPostalCode>HK 01</ShippingPostalCode><ShippingCountry>HK</ShippingCountry><ShippingEmail>[email protected]</ShippingEmail></BillingAndShippingInfo><RequestAdditionalResponseData><TransactionDetailExFlag>Y</TransactionDetailExFlag></RequestAdditionalResponseData><MCPInfo><MCPAmount>780</MCPAmount><MCPCurrencyCode>826</MCPCurrencyCode></MCPInfo></req></AuthorizationMCP></soapenv:Body></soapenv:Envelope></send><recv type="string"><?xml version="1.0"?>
  6. <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><AuthorizationMCPResponse xmlns="http://www.planetpayment.net"><AuthorizationMCPResult><ResponseInfo><ResponseDetail><ResponseCode>00</ResponseCode><ResponseMessage>Approved</ResponseMessage><LocalTransactionDate>08/27/2019</LocalTransactionDate><LocalTransactionTime>12:02:07:0811</LocalTransactionTime><RequestIdentifier>5d655400b7119</RequestIdentifier><RetrievalReferenceNumber>923941557411</RetrievalReferenceNumber><ProcessingTime>00:00:156</ProcessingTime></ResponseDetail><ResponseTransactionDetail><AVSResponseCode>Y</AVSResponseCode><CVVResponseCode>M</CVVResponseCode><AuthorizationSourceCode>5</AuthorizationSourceCode><AuthorizationNumber>16875A</AuthorizationNumber><CardAccountNumber>****************</CardAccountNumber><TransactionAmount>906</TransactionAmount><TransactionCurrencyCode>840</TransactionCurrencyCode><CardholderBillingTransactionAmount>780</CardholderBillingTransactionAmount><CardholderBillingTransactionCurrencyCode>826</CardholderBillingTransactionCurrencyCode></ResponseTransactionDetail><EMVResponseData/><Planet3DSecureResponseData><ECI>7</ECI></Planet3DSecureResponseData></ResponseInfo><ResponseMCPInfo><MCPAmount>780</MCPAmount><MCPCurrencyCode>826</MCPCurrencyCode><MCPTransactionConversionRate>1161257</MCPTransactionConversionRate><MCPTransactionConversionExponent>6</MCPTransactionConversionExponent><MCPTransactionConvertedAmount>906</MCPTransactionConvertedAmount><MCPLocalTransactionDate>08/27/2019</MCPLocalTransactionDate><MCPLocalTransactionTime>12:02:07:0811</MCPLocalTransactionTime></ResponseMCPInfo></AuthorizationMCPResult></AuthorizationMCPResponse></s:Body></s:Envelope>
  7. </recv></auth><RequestIdentifier type="string">5d655400b7119</RequestIdentifier><RetrievalReferenceNumber type="string">923941557411</RetrievalReferenceNumber><processorXref type="string">923941557411</processorXref><void type="array"><send type="string"><?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header/><soapenv:Body><VoidTransaction xmlns="http://www.planetpayment.net"><req><AccessInfo><User>321400000002</User><Password>**************</Password><TerminalID>90000101</TerminalID><ApplicationID>Cardstream v3</ApplicationID><GatewayTransactionId>10017683</GatewayTransactionId></AccessInfo><RequestIdentifier>5d655400b7119</RequestIdentifier><RetrievalReferenceNumber>923941557411</RetrievalReferenceNumber></req></VoidTransaction></soapenv:Body></soapenv:Envelope></send><recv type="string"><?xml version="1.0"?>
  8. <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><VoidTransactionResponse xmlns="http://www.planetpayment.net"><VoidTransactionResult><ResponseDetail><ResponseCode>00</ResponseCode><ResponseMessage>Approved</ResponseMessage><LocalTransactionDate>08/27/2019</LocalTransactionDate><LocalTransactionTime>12:02:09:0390</LocalTransactionTime><RequestIdentifier>5d655400b7119</RequestIdentifier><RetrievalReferenceNumber>923941557411</RetrievalReferenceNumber><ProcessingTime>00:00:218</ProcessingTime></ResponseDetail><ResponseVoidTransactionDetail><CardAccountNumber>****************</CardAccountNumber><TransactionAmount>906</TransactionAmount><TransactionCurrencyCode>840</TransactionCurrencyCode><OriginalRetrievalReferenceNumber>923941557411</OriginalRetrievalReferenceNumber></ResponseVoidTransactionDetail></VoidTransactionResult></VoidTransactionResponse></s:Body></s:Envelope>
  9. </recv></void><_extendedData type="array"><riskCheckEnabled type="string">N</riskCheckEnabled><surchargeEnabled type="string">N</surchargeEnabled><requestMerchantID type="string">110053</requestMerchantID><processMerchantID type="string">110053</processMerchantID><paymentMethod type="string">card</paymentMethod><merchantType type="string">iusdfiksdfhnfvhvgedj</merchantType><merchantOriginalOrderRef type="string">ksdaskdjhaksjdh</merchantOriginalOrderRef><shippingTaxReason type="string">VAT</shippingTaxReason><shippingDiscountAmount type="integer">100</shippingDiscountAmount><shippingDiscountReason type="string">Frequent Flyer</shippingDiscountReason><facilitatorName type="string">ASDA STORES</facilitatorName><facilitatorID type="string">9876543210</facilitatorID><subMerchantID type="string">0123456789</subMerchantID><surchargeRequired type="string">N</surchargeRequired><cardType type="string">Visa Credit</cardType><cardTypeCode type="string">VC</cardTypeCode><cardScheme type="string">Visa</cardScheme><cardSchemeCode type="string">VC</cardSchemeCode><cardIssuer type="string">Unknown</cardIssuer><cardIssuerCountry type="string">Unknown</cardIssuerCountry><cardIssuerCountryCode type="string">XXX</cardIssuerCountryCode><cardProductCode type="string">0</cardProductCode><cardFlags type="integer">6225924</cardFlags><cardNumberValid type="string">Y</cardNumberValid><cancelReason type="string">Automatic authorisation void, preauth only</cancelReason><vcsResponseCode type="integer">0</vcsResponseCode><vcsResponseMessage type="string">Success - no velocity check rules applied</vcsResponseMessage><acquirerResponseCode type="string">00</acquirerResponseCode><acquirerResponseMessage type="string">Approved</acquirerResponseMessage></_extendedData></mysql>
  10. EOS;
  11.  
  12. $data = P3Xml::decode($processor_data);
  13.  
  14. //echo 'Send: ' . var_export($data['auth']['send'], true) . PHP_EOL;
  15.  
  16. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  17. // Example 1: Preserving namespaces
  18. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  19.  
  20. echo 'Namespaces preserved' . PHP_EOL;
  21. echo '~~~~~~~~~~~~~~~~~~~~' . PHP_EOL;
  22.  
  23. $xml = simplexml_load_string($data['auth']['send']);
  24.  
  25. // Or if you think they may be syntax errors (unlikely in this case)
  26. /*
  27. if (($xml = P3Xml::load($data['auth']['send'], 'SimpleXmlElement', null, $errmsg)) === false) {
  28.     die('error: ' . var_export($errmsg, true). PHP_EOL);
  29. }
  30. */
  31.  
  32.  
  33. //echo 'XML: ' . var_export($xml->asXml(), true) . PHP_EOL;
  34.  
  35. // Access part of Planet request
  36. echo 'User: ' . (string)$xml->children('http://schemas.xmlsoap.org/soap/envelope/')->Body->children('http://www.planetpayment.net')->AuthorizationMCP->req->AccessInfo->User . PHP_EOL;
  37.  
  38. // Or using Xpath
  39. $xml->registerXPathNamespace('s', 'http://schemas.xmlsoap.org/soap/envelope/');
  40. $xml->registerXPathNamespace('p', 'http://www.planetpayment.net');
  41. echo 'User: ' . (string)$xml->xpath('/s:Envelope/s:Body/p:AuthorizationMCP/p:req/p:AccessInfo/p:User')[0] . PHP_EOL;
  42.  
  43. unset($xml);
  44.  
  45. echo PHP_EOL . PHP_EOL;
  46.  
  47. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  48. // Example 2: Stripping namespaces
  49. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  50.  
  51. echo 'Namespaces stripped' . PHP_EOL;
  52. echo '~~~~~~~~~~~~~~~~~~~' . PHP_EOL;
  53.  
  54. $send = preg_replace('%(</?)(?:[\\w-]+:)([\\w-]+)%', '\\1\\2', $data['auth']['send']);
  55. $send = preg_replace('%xmlns(?::[\\w-]+)?="[^"]+"%', '', $send);
  56.  
  57. //var_export($send);
  58.  
  59.         
  60. $xml = simplexml_load_string($send);
  61.  
  62. // Or if you think they may be syntax errors (unlikely in this case)
  63. /*
  64. if (($xml = P3Xml::load($data['auth']['send'], 'SimpleXmlElement', null, $errmsg)) === false) {
  65.     die('error: ' . var_export($errmsg, true). PHP_EOL);
  66. }
  67. */
  68.  
  69. //echo 'XML: ' . var_export($xml->asXml(), true) . PHP_EOL;
  70.  
  71. // Access part of Planet request
  72. echo 'User: ' . (string)$xml->Body->AuthorizationMCP->req->AccessInfo->User . PHP_EOL;
  73.  
  74. // Or using Xpath
  75. echo 'User: ' . (string)$xml->xpath('/Envelope/Body/AuthorizationMCP/req/AccessInfo/User')[0] . PHP_EOL;
  76.  
  77. // Slow convert to an array (not possible if namespaces are presevered)
  78. echo 'array: ' . var_export(P3Xml::decode($send), true) . PHP_EOL;
  79.  
  80. // Quick convert to an array (not possible if namespaces are presevered)
  81. echo 'array: ' . var_export(json_decode(json_encode($xml), true), true) . PHP_EOL;
  82.  
  83.  
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
  90.  
  91.  
  92.  
  93.  
  94. /**
  95.  *
  96.  * PLATFORM 3 - XML Utilities
  97.  * ==========================
  98.  *
  99.  * This class provides various static methods for handling XML formatted
  100.  * strings and libXml based objects.
  101.  *
  102.  * @package           Cardstream
  103.  * @subpackage        Shared/Classes
  104.  * @copyright Copyright (c) 2011 - Cardstream Ltd.
  105.  * @author            Nick Turner <[email protected]>
  106.  * @link              http://www.cardstream.com
  107.  * @version           $Id$
  108.  */
  109.  
  110. /**
  111.  * XML Utilities.
  112.  *
  113.  * This is a small static class containing methods used to manipulate XML
  114.  * formatted strings and objects.
  115.  *
  116.  * @author            Nick Turner <[email protected]>
  117.  * @static
  118.  * @cs ignore NoNamespace
  119.  */
  120. class P3Xml {
  121.  
  122.         /**
  123.          * Convert all applicable characters to XML entities.
  124.          *
  125.          * This is the equivalent to the PHP {@link htmlentities()} but for XML.
  126.          *
  127.          * @param     string          $str            string to convert
  128.          * @return    string                                  converted string
  129.          */
  130.         static public function entities($str) {
  131.                 static $tr = array(
  132.                         '&#'    => '&#',
  133.                         '&'             => '&',
  134.                         '\''    => '&apos;',
  135.                         '<'             => '<',
  136.                         '>'             => '>',
  137.                         '"'             => '"',
  138.                 );
  139.                 return strtr($str, $tr);
  140.         }
  141.  
  142.         /**
  143.          * Convert associative array to XML attribute list.
  144.          *
  145.          * The array keys are expected to be valid values for use as XML
  146.          * attribute names, the values will be enclosed in double quotes and
  147.          * escaped using {@link P3Xml::entities()}.
  148.          *
  149.          * For example:
  150.          * <pre>
  151.          * $a = P3Xml::attrs(array('a' => '<apple>', 'b' => '<banana>'));
  152.          * $a === 'a="<apple>" b="<banana>"';
  153.          * </pre>
  154.          *
  155.          * @param     array           $attrs          attributes to convert
  156.          * @return    string                                  converted string
  157.          */
  158.         static public function attrs(array $attrs) {
  159.                 return join(' ', array_map(function($k, $v) { return P3Xml::entities($k) . '="' . P3Xml::entities($v) . '"'; }, array_keys($attrs), array_values($attrs)));
  160.         }
  161.  
  162.         /**
  163.          * Load an XML string.
  164.          *
  165.          * This will load an XML string into a libXml DOM which can then be
  166.          * accessed via a {@link DOMDocument} or a {@link SimpleXmlElement}
  167.          * which will be returned.
  168.          *
  169.          * The method will create an object of $class, which must be derived from
  170.          * either the SimpleXmlElement class otherwise the method will throw an
  171.          * InvalidArgumentException.
  172.          *
  173.          * The created object is then used to load the XML string an if the load
  174.          * is successful then the method returns the object otherwise it deletes
  175.          * it and returns null, placing the last error message in $errmsg.
  176.          *
  177.          * @param     string          $str            XML formatted string to load
  178.          * @param     string          $class          name of class to load into
  179.          * @param     array           $options        bitwise OR of the libxml options
  180.          * @param     string          $errmsg         string to return any error message
  181.          * @return    object                                  object of class $class (or null)
  182.          * @throws    InvalidArgumentException
  183.          */
  184.         static public function load($str, $class = 'SimpleXmlElement', $options = null, &$errmsg = null) {
  185.                 libxml_clear_errors();
  186.                 libxml_use_internal_errors(true);
  187.  
  188.                 if (!$class || strcasecmp($class, 'SimpleXmlElement') === 0 || is_subclass_of($class, 'SimpleXmlElement')) {
  189.                         $ret = simplexml_load_string($str, $class, $options);
  190.                 } else if (strcasecmp($class, 'DOMDocument') === 0 || is_subclass_of($class, 'DOMDocument')) {
  191.                         $ret = new $class();
  192.                         if (!$ret->loadXml($str, $options)) {
  193.                                 unset($ret);
  194.                                 $ret = false;
  195.                         }
  196.                 } else {
  197.                         throw new InvalidArgumentException('Class must be or derived from either SimpleXmlElement or DOMDocument');
  198.                 }
  199.                
  200.                 if ($ret === false) {
  201.                         if (($e = libxml_get_last_error())) {
  202.                                 $errmsg = trim($e->message) . " at line {$e->line}.{$e->column}";
  203.                         } else {
  204.                                 $errmsg = 'Unknown error';
  205.                         }
  206.                 }
  207.  
  208.                 return $ret;
  209.         }
  210.  
  211.         /**
  212.          * Return an XML node or attribute object identified by a given Xpath
  213.          * expression.
  214.          *
  215.          * This evaluate the $xpath Xpath expression to determine a node in the $xml
  216.          * libXml DOM. If the expression matches more than one node then the first
  217.          * is used.
  218.          *
  219.          * If required the $attr attribute is located on the found node and it is
  220.          * returned instead of the node.
  221.          *
  222.          * The libXml DOM must be provided using an object which must be derived
  223.          * from either the SimpleXmlElement class or the DOMDocument class,
  224.          * otherwise the method will throw an InvalidArgumentException.
  225.          *
  226.          * If the expression doesn't match any XML node or if the node doesn't
  227.          * have any required attribute then the method returns null.
  228.          *
  229.          * @param     object          $xml            libXML DOM object
  230.          * @param     string          $xpath          Xpath expression
  231.          * @param     string          $attr           attribute name
  232.          * @return    object                                  node or attribute object (or null)
  233.          * @throws    InvalidArgumentException
  234.          */
  235.         static public function item($xml, $xpath, $attr = null) {
  236.                 if (is_a($xml, 'SimpleXmlElement')) {
  237.                         $nodes = $xml->xpath($xpath);
  238.                         $ret = (isset($nodes[0]) ? ($attr ((isset($nodes[0][$attr])) ? $nodes[0][$attr] : null) : $nodes[0]) : null);
  239.                 } else if (is_a($xml, 'DOMNode')) {
  240.                         $x = new DOMXPath((is_a($xml, 'DOMDocument') ? $xml : $xml->ownerDocument));
  241.                         $nodes = $x->query($xpath, $xml);
  242.                         $ret = (($n = $nodes->item(0)) ? ($attr ($n->hasAttribute($attr) ? $n->getAttributeNode($attr) : null) : $n) : null);
  243.                 } else {
  244.                         throw new InvalidArgumentException('XML root must be either a SimpleXmlElement or a DOMNode');
  245.                 }
  246.                 return $ret;
  247.         }
  248.  
  249.         /**
  250.          * Copy an XML node to a new parent node.
  251.          *
  252.          * This will clone the given node and add it as a new child of the given
  253.          * parent. The node and parent do not have to existing in the same DOM.
  254.          *
  255.          * The parent and node objects must both be derived from either the
  256.          * SimpleXmlElement class or the DOMDocument class, otherwise the method
  257.          * will throw an InvalidArgumentException.
  258.          *
  259.          * @param     object          $parent         parent to add copy to
  260.          * @param     object          $node           node to copy
  261.          * @return    object                                  new child node of parent
  262.          * @throws    InvalidArgumentException
  263.          */
  264.         static public function copy($parent, $node) {
  265.                 if (is_a($parent, 'SimpleXmlElement') && is_a($node, 'SimpleXmlElement')) {
  266.                         $parent = dom_import_simplexml($parent);
  267.                         $node = dom_import_simplexml($node);
  268.                         return simplexml_import_dom(self::copy($parent, $node));
  269.                 } else if (is_a($parent, 'DOMNode') && is_a($node, 'DOMNode')) {
  270.                         if ($parent->ownerDocument === $node->ownerDocument) {
  271.                                 return $parent->appendChild($node->cloneNode(true));
  272.                         } else {
  273.                                 return $parent->appendChild($parent->ownerDocument->importNode($node, true));
  274.                         }
  275.                 } else {
  276.                         throw new InvalidArgumentException('Node must be either a SimpleXmlElement or a DOMNode');
  277.                 }
  278.         }
  279.  
  280.         /**
  281.          * Decode an XML encoded string into a PHP variable.
  282.          *
  283.          * This take a XML encoded string as and return a native PHP variable.
  284.          * It is for XML what {@link json_decode()} is for JSON.
  285.          *
  286.          * The XML encoded string must use plain XML text nodes with no attributes
  287.          * etc., such as is created by the {@link encode()} method of this class.
  288.          *
  289.          * The $xml parameter can either be a string or a libXml object derived from
  290.          * either the SimpleXmlElement class or the DOMDocument class, otherwise the
  291.          * method will throw an InvalidArgumentException.
  292.          *
  293.          * @param     mixed           $xml            xml encoded string or libXml object
  294.          * @return    mixed                                   PHP variable (or null)
  295.          * @throws    InvalidArgumentException
  296.          */
  297.         static public function decode($xml) {
  298.                 libxml_clear_errors();
  299.                 libxml_use_internal_errors(true);
  300.                 if (is_string($xml)) {
  301.                         $xml = simplexml_load_string($xml);
  302.                         return self::decode($xml);
  303.                 } else if (is_a($xml, 'DOMNode')) {
  304.                         $xml = simplexml_import_dom($xml);
  305.                         return self::decode($xml);
  306.                 } else if (!is_a($xml, 'SimpleXmlElement')) {
  307.                         throw new InvalidArgumentException('Argument must be either an XML formatted string, an SimpleXmlElement or a DOMNode');
  308.                 }
  309.                 if ($xml->count()) {
  310.                         $ret = array();
  311.                         foreach ($xml as $k => $v) {
  312.                                 $n = (isset($v['id']) ? (ctype_digit($v['id']) ? (int)$v['id'] : (string)$v['id']) : $k);
  313.                                 $ret[$n] = self::decode($v);
  314.                         }
  315.                 } else {
  316.                         $ret = (string)$xml;
  317.                 }
  318.                 if (isset($xml['type'])) {
  319.                         $type = (string)$xml['type'];
  320.                         if (($type === 'array' || $type === 'object') && $ret === '') {
  321.                                 $ret = null;
  322.                         }
  323.                         if ($type === 'object' && isset($xml['class']) && ($class = (string)$xml['class']) !== 'stdClass') {
  324.                                 if (!method_exists($class, '__set_state')) {
  325.                                         throw new RuntimeException('Cannot decode class: ' . $class);
  326.                                 }
  327.                                 $ret = $class::__set_state((array)$ret);
  328.                         } else if ($type === 'boolean') {
  329.                                 $ret = ($ret === 'TRUE');
  330.                         } else if ($type === 'string' && isset($xml['escaped'])) {
  331.                                 if ((string)$xml['escaped'] !== 'cs') {
  332.                                         throw new RuntimeException('Unknown string escaping type: ' . $xml['escaped']);
  333.                                 }
  334.                                 $ret = ($ret === '' ? '' : stripcslashes($ret));
  335.                         } else {
  336.                                 settype($ret, $type);
  337.                         }
  338.                 }
  339.                 return $ret;
  340.         }
  341.  
  342.         /**
  343.          * Encode a PHP variable as XML encoded string.
  344.          *
  345.          * This takes a native PHP variable and returns an XML encoded string.
  346.          * It is for XML what {@link json_encode()} is for JSON.
  347.          *
  348.          * The PHP variable must be a scalar variable or array of scalar variables,
  349.          * otherwise the method will throw an InvalidArgumentException.
  350.          *
  351.          * The $output parameter determines the return type and can be either
  352.          * 'string', 'SimpleXmlElement' or 'DOMNode', otherwise the method will
  353.          * throw an InvalidArgumentException.
  354.          *
  355.          * @param     string          $val            PHP value to encode
  356.          * @param     string          $output         output type
  357.          * @param     string          $charset        xml character set
  358.          * @param     string          $root           root tag name
  359.          * @return    mixed                                   PHP variable (or null)
  360.          * @throws    InvalidArgumentException
  361.          */
  362.         static public function encode($val, $output = 'string', $charset = 'UTF-8', $root = 'p3xml') {
  363.                 static $ctl =  "\000\001\002\003\004\005\006\007\010\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037";
  364.                 static $ctlbs = "\000\001\002\003\004\005\006\007\010\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\\";
  365.  
  366.                 if (is_a($output, 'SimpleXmlElement')) {
  367.                         $node = $output;
  368.                         $node['type'] = $type = gettype($val);
  369.                         if ($type === 'array' || $type === 'object') {
  370.                                 $tag = $node->getName();
  371.                                 if ($type === 'object') {
  372.                                         $node['class'] = get_class($val);
  373.                                 }
  374.                                 $i = ($tag === $root 'item' : $tag);
  375.                                 foreach ((array)$val as $k => $v) {
  376.                                         if (is_int($k) || !preg_match('/^[_A-Za-z][_A-Za-z0-9]*$/', $k)) {
  377.                                                 $child = $node->addChild($i);
  378.                                                 $child['id'] = $k;
  379.                                         } else {
  380.                                                 $child = $node->addChild($k);
  381.                                         }
  382.                                         self::encode($v, $child, $charset, $root);
  383.                                 }
  384.                         } else if ($type === 'boolean') {
  385.                                 $node[0] = ($val 'TRUE' : 'FALSE');
  386.                         } else if ($type === 'integer' || $type === 'double') {
  387.                                 $node[0] = $val;
  388.                         } else if ($type === 'string') {
  389.                                 // Have to escape control characters until we can use XML v1.1
  390.                                 if ($val === '') {
  391.                                         // Don't add any node content
  392.                                 } else if (strcspn($val, $ctl) === strlen($val)) {
  393.                                         $node[0] = $val;
  394.                                 } else {
  395.                                         $node[0] = addcslashes($val, $ctlbs);
  396.                                         $node['escaped'] = 'cs';
  397.                                 }
  398.                         } else if ($val === null) {
  399.                                 // Don't add any node content
  400.                         } else {
  401.                                 throw new InvalidArgumentException('Unsupported data type: ' . gettype($val));
  402.                         }
  403.                 } else {
  404.                         $xml = new SimpleXmlElement('<?xml version="1.0" encoding="' . self::entities($charset) . '"?' . '><' . $root . '/>');
  405.                         self::encode($val, $xml, $charset, $root);
  406.                         switch ($output) {
  407.                                 case 'SimpleXmlElement':
  408.                                         return $xml;
  409.                                 case 'DOMNode':
  410.                                         return dom_import_simplexml($xml);
  411.                                 default:
  412.                                         return trim($xml->asXml());
  413.                         }
  414.                 }
  415.         }
  416.  
  417.         /**
  418.          * Format XML into a string.
  419.          *
  420.          * This will take a XML encoded string and return it nicely formatted with
  421.          * indentation etc.
  422.          *
  423.          * The $xml parameter can either be a string or a libXml object derived from
  424.          * either the SimpleXmlElement class or the DOMDocument class, otherwise the
  425.          * method will throw an InvalidArgumentException.
  426.          *
  427.          * If $xml is not a valid XML formatted string then it will be returned
  428.          * unformatted.
  429.          *
  430.          * @param     mixed           $xml            xml encoded string or libXml object
  431.          * @return    mixed                                   formated string (or original)
  432.          * @throws    InvalidArgumentException
  433.          */
  434.         static public function format($xml) {
  435.                 libxml_clear_errors();
  436.                 libxml_use_internal_errors(true);
  437.                 if (is_string($xml)) {
  438.                         $doc = new DOMDocument();
  439.                         if (!$doc->loadXml($xml)) {
  440.                                 return $xml;
  441.                         }
  442.                 } else if (is_a($xml, 'SimpleXmlElement')) {
  443.                         $doc = new DOMDocument();
  444.                         $doc->importNode(dom_import_simplexml($xml), true);
  445.                 } else if (is_a($xml, 'DOMNode')) {
  446.                         $doc = $xml->ownerDocument;
  447.                 } else {
  448.                         throw new InvalidArgumentException('Argument must be either an XML formatted string, an SimpleXmlElement or a DOMNode');
  449.                 }
  450.                 $doc->preserveWhiteSpace = false;
  451.                 $doc->formatOutput = true;
  452.                 return $doc->saveXml();
  453.         }
  454. }
  455.  
  456. /* vim: set noexpandtab tabstop=4 shiftwidth=4: */
  457.  
  458.  
File Description
  • XML decoding Planet request from transaction processor data
  • PHP Code
  • 27 Aug-2019
  • 24.57 Kb
You can Share it: