mirror of
https://gitee.com/ShopeX/OMS
synced 2026-03-22 18:35:35 +08:00
236 lines
8.4 KiB
PHP
236 lines
8.4 KiB
PHP
<?php
|
|
/**
|
|
* Copyright 2012-2026 ShopeX (https://www.shopex.cn)
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
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;
|
|
}
|
|
|
|
} |