mirror of
https://gitee.com/ShopeX/OMS
synced 2026-03-23 02:45:33 +08:00
225 lines
7.9 KiB
PHP
225 lines
7.9 KiB
PHP
<?php
|
||
/**
|
||
* Copyright © ShopeX (http://www.shopex.cn). All rights reserved.
|
||
* See LICENSE file for license details.
|
||
*/
|
||
|
||
class erpapi_format_xml extends erpapi_format_abstract{
|
||
private static $xml = null;
|
||
private static $encoding = 'UTF-8';
|
||
|
||
/**
|
||
* Initialize the root XML node [optional]
|
||
* @param $version
|
||
* @param $encoding
|
||
* @param $format_output
|
||
*/
|
||
public static function init($version = '1.0', $encoding = 'UTF-8', $format_output = true) {
|
||
self::$xml = new DomDocument($version, $encoding);
|
||
self::$xml->formatOutput = $format_output;
|
||
self::$encoding = $encoding;
|
||
}
|
||
|
||
/**
|
||
* Convert an Array to XML
|
||
* @param string $node_name - name of the root node to be converted
|
||
* @param array $arr - aray to be converterd
|
||
* @return DomDocument
|
||
*/
|
||
public function data_encode($arr=array()) {
|
||
$xml = self::getXMLRoot();
|
||
|
||
reset($arr);
|
||
if (count($arr) == 1) {
|
||
$node_name = key($arr); $data = $arr[$node_name];
|
||
} else {
|
||
$node_name = 'response'; $data = $arr;
|
||
}
|
||
|
||
$node_name = count($arr) == 1 ? key($arr) : 'response';
|
||
|
||
$xml->appendChild(self::array2xml($node_name, $data));
|
||
self::$xml = null;
|
||
|
||
return $xml->saveXML();
|
||
}
|
||
|
||
/**
|
||
* Convert an Array to XML
|
||
* @param string $node_name - name of the root node to be converted
|
||
* @param array $arr - aray to be converterd
|
||
* @return DOMNode
|
||
*/
|
||
private static function &array2xml($node_name, $arr=array()) {
|
||
//print_arr($node_name);
|
||
$xml = self::getXMLRoot();
|
||
$node = $xml->createElement($node_name);
|
||
|
||
if(is_array($arr)){
|
||
// get the attributes first.;
|
||
if(isset($arr['@attributes'])) {
|
||
foreach($arr['@attributes'] as $key => $value) {
|
||
if(!self::isValidTagName($key)) {
|
||
continue;
|
||
}
|
||
|
||
$node->setAttribute($key, self::bool2str($value));
|
||
}
|
||
unset($arr['@attributes']); //remove the key from the array once done.
|
||
}
|
||
|
||
// check if it has a value stored in @value, if yes store the value and return
|
||
// else check if its directly stored as string
|
||
if(isset($arr['@value'])) {
|
||
$node->appendChild($xml->createTextNode(self::bool2str($arr['@value'])));
|
||
unset($arr['@value']); //remove the key from the array once done.
|
||
//return from recursion, as a note with value cannot have child nodes.
|
||
return $node;
|
||
} else if(isset($arr['@cdata'])) {
|
||
$node->appendChild($xml->createCDATASection(self::bool2str($arr['@cdata'])));
|
||
unset($arr['@cdata']); //remove the key from the array once done.
|
||
//return from recursion, as a note with cdata cannot have child nodes.
|
||
return $node;
|
||
}
|
||
}
|
||
|
||
//create subnodes using recursion
|
||
if(is_array($arr)){
|
||
// recurse to get the node for that key
|
||
foreach($arr as $key=>$value){
|
||
if(!self::isValidTagName($key)) {
|
||
continue;
|
||
}
|
||
|
||
if(is_array($value) && is_numeric(key($value))) {
|
||
// MORE THAN ONE NODE OF ITS KIND;
|
||
// if the new array is numeric index, means it is array of nodes of the same kind
|
||
// it should follow the parent key name
|
||
foreach($value as $k=>$v){
|
||
$node->appendChild(self::array2xml($key, $v));
|
||
}
|
||
} else {
|
||
// ONLY ONE NODE OF ITS KIND
|
||
$node->appendChild(self::array2xml($key, $value));
|
||
}
|
||
unset($arr[$key]); //remove the key from the array once done.
|
||
}
|
||
}
|
||
// after we are done with all the keys in the array (if it is one)
|
||
// we check if it has any text value, if yes, append it.
|
||
if(!is_array($arr)) {
|
||
$node->appendChild($xml->createTextNode(self::bool2str($arr)));
|
||
}
|
||
return $node;
|
||
}
|
||
|
||
/*
|
||
* Get the root XML node, if there isn't one, create it.
|
||
*/
|
||
private static function getXMLRoot(){
|
||
if(empty(self::$xml)) {
|
||
self::init();
|
||
}
|
||
return self::$xml;
|
||
}
|
||
/*
|
||
* Get string representation of boolean value
|
||
*/
|
||
private static function bool2str($v){
|
||
//convert boolean to text value.
|
||
$v = $v === true ? 'true' : $v;
|
||
$v = $v === false ? 'false' : $v;
|
||
return $v;
|
||
}
|
||
/*
|
||
* Check if the tag name or attribute name contains illegal characters
|
||
* Ref: http://www.w3.org/TR/xml/#sec-common-syn
|
||
*/
|
||
private static function isValidTagName($tag){
|
||
$pattern = '/^[a-z_]+[a-z0-9\:\-\.\_]*[^:]*$/i';
|
||
return preg_match($pattern, $tag, $matches) && $matches[0] == $tag;
|
||
}
|
||
|
||
|
||
/**
|
||
* data_decode
|
||
* @param mixed $input_xml input_xml
|
||
* @return mixed 返回值
|
||
*/
|
||
public function data_decode($input_xml) {
|
||
$xml = self::getXMLRoot();
|
||
|
||
if(is_string($input_xml)) {
|
||
$parsed = $xml->loadXML($input_xml);
|
||
if(!$parsed) {
|
||
return array();
|
||
}
|
||
|
||
} else {
|
||
return array();
|
||
}
|
||
|
||
$array[$xml->documentElement->tagName] = self::xml2array($xml->documentElement);
|
||
|
||
self::$xml = null; // clear the xml node in the class for 2nd time use.
|
||
return $array;
|
||
}
|
||
|
||
private static function &xml2array($node) {
|
||
$output = array();
|
||
switch ($node->nodeType) {
|
||
case XML_CDATA_SECTION_NODE:
|
||
$output['@cdata'] = trim($node->textContent);
|
||
break;
|
||
case XML_TEXT_NODE:
|
||
$output = trim($node->textContent);
|
||
break;
|
||
case XML_ELEMENT_NODE:
|
||
// for each child node, call the covert function recursively
|
||
for ($i=0, $m=$node->childNodes->length; $i<$m; $i++) {
|
||
$child = $node->childNodes->item($i);
|
||
$v = self::xml2array($child);
|
||
if(isset($child->tagName)) {
|
||
$t = $child->tagName;
|
||
// assume more nodes of same kind are coming
|
||
if(!isset($output[$t])) {
|
||
$output[$t] = array();
|
||
}
|
||
$output[$t][] = $v;
|
||
} else {
|
||
//check if it is not an empty text node
|
||
if($v !== '') {
|
||
$output = $v;
|
||
}
|
||
}
|
||
}
|
||
if(is_array($output)) {
|
||
// if only one node of its kind, assign it directly instead if array($value);
|
||
foreach ($output as $t => $v) {
|
||
if(is_array($v) && count($v)==1) {
|
||
$output[$t] = $v[0];
|
||
}
|
||
}
|
||
if(empty($output)) {
|
||
//for empty nodes
|
||
$output = '';
|
||
}
|
||
}
|
||
// loop through the attributes and collect them
|
||
if($node->attributes->length) {
|
||
$a = array();
|
||
foreach($node->attributes as $attrName => $attrNode) {
|
||
$a[$attrName] = (string) $attrNode->value;
|
||
}
|
||
// if its an leaf node, store the value in @value instead of directly storing it.
|
||
if(!is_array($output)) {
|
||
$output = array('@value' => $output);
|
||
}
|
||
$output['@attributes'] = $a;
|
||
}
|
||
break;
|
||
}
|
||
return $output;
|
||
}
|
||
|
||
} |