PHP中有没有像json_encode()这样的xml_encode()?
Posted
技术标签:
【中文标题】PHP中有没有像json_encode()这样的xml_encode()?【英文标题】:Is there an xml_encode() like json_encode() in PHP? 【发布时间】:2011-11-28 08:59:52 【问题描述】:在 php 中,使用 json_encode()
很容易传回 json 对象。
但是,是否有与此等效的 XML?
【问题讨论】:
【参考方案1】:您可以定义自己的xml_encode()
函数,例如来自http://darklaunch.com/2009/05/23/php-xml-encode-using-domdocument-convert-array-to-xml-json-encode 的函数
function xml_encode($mixed, $domElement=null, $DOMDocument=null)
if (is_null($DOMDocument))
$DOMDocument =new DOMDocument;
$DOMDocument->formatOutput = true;
xml_encode($mixed, $DOMDocument, $DOMDocument);
echo $DOMDocument->saveXML();
else
// To cope with embedded objects
if (is_object($mixed))
$mixed = get_object_vars($mixed);
if (is_array($mixed))
foreach ($mixed as $index => $mixedElement)
if (is_int($index))
if ($index === 0)
$node = $domElement;
else
$node = $DOMDocument->createElement($domElement->tagName);
$domElement->parentNode->appendChild($node);
else
$plural = $DOMDocument->createElement($index);
$domElement->appendChild($plural);
$node = $plural;
if (!(rtrim($index, 's') === $index))
$singular = $DOMDocument->createElement(rtrim($index, 's'));
$plural->appendChild($singular);
$node = $singular;
xml_encode($mixedElement, $node, $DOMDocument);
else
$mixed = is_bool($mixed) ? ($mixed ? 'true' : 'false') : $mixed;
$domElement->appendChild($DOMDocument->createTextNode($mixed));
【讨论】:
工作正常,只是要小心,它太聪明了——如果你有一个以“s”结尾的标签名称——它会自动生成一个单数形式的标签并将其添加到里面...(例如,在制作具有不应有任何“坐标”子标签的“坐标”标签的 kml 时尝试):-P【参考方案2】:JSON 可以原生表达 php 数组、整数、字符串等。 XML 没有这样的概念——只有元素、属性和文本。如果要逐字传输对象,请使用 JSON。如果要实现复杂的 API,请使用 XML,例如 php DOM interface。
【讨论】:
请注意,JSON 不是二进制安全的,这意味着您不能安全地将任何可能包含二进制数据的变量添加到 json。 (这意味着,例如,您不能通过 JSON 安全地发送 PDF) - 例如,这 非常 可能会失败并且只返回 bool(false): json encoding error:<?php var_dump(json_encode(array('bin'=>random_bytes(1337))));
我作弊,我将二进制数据转换为字符串数据并使用 json 发送。在另一端,您只需将其再次转换回来。【参考方案3】:
你可以使用xmlrpc_encode
。
xmlrpc_encode ($your_array);
请小心,因为此功能是实验性的。
参考:http://php.net/manual/en/function.xmlrpc-encode.php
【讨论】:
这是一个 noce 函数,但有时会动摇。 确实,自 PHP 4.1.0 起,21 年前的实验性版本。【参考方案4】:这里是 php7.0+ 的一个,我敢打赌它远非最佳,代码很重要,并且 没有 进行了很多测试,但至少它适用于我的数据(不像 Seph 的代码)...
示例:
$test = array (
'normal1' => 'foo',
'normal2' => 'bar',
'foo_assoc' => [
'foo',
'bar',
'baz',
[
'derp',
'derpmore'
]
],
'foo_nonassoc' => [
'derppp' => 'yes',
'daarpp' => 'no',
'lel',
'far' => 'away'
],
'normal3' => 'lala',
'deep' => [
'deeper' => [
'deeper2' => [
'deepest' => [
'quite',
'deep',
'indeed'
],
'checkmate'
]
]
],
'special' => 'encoding<special>characters&test',
'me_n_you' => 'true'
);
echo (hhb_xml_encode ( $test ));
输出:
<normal1>foo</normal1>
<normal2>bar</normal2>
<foo_assoc>foo</foo_assoc>
<foo_assoc>bar</foo_assoc>
<foo_assoc>baz</foo_assoc>
<foo_assoc>derp</foo_assoc>
<foo_assoc>derpmore</foo_assoc>
<foo_nonassoc>
<derppp>yes</derppp>
<daarpp>no</daarpp>
<foo_nonassoc>lel</foo_nonassoc>
<far>away</far>
</foo_nonassoc>
<normal3>lala</normal3>
<deep>
<deeper>
<deeper2>
<deepest>quite</deepest>
<deepest>deep</deepest>
<deepest>indeed</deepest>
<deeper2>checkmate</deeper2>
</deeper2>
</deeper>
</deep>
<special>encoding<special>characters&test</special>
<me_n_you>true</me_n_you>
功能:
编辑:修复了编码空数组的错误。 编辑:使代码与 PHP8 兼容 function hhb_xml_encode(array $arr, string $name_for_numeric_keys = 'val'): string
if (empty ( $arr ))
// avoid having a special case for <root/> and <root></root> i guess
return '';
$is_iterable_compat = function ($v): bool
// php 7.0 compat for php7.1+'s is_itrable
return is_array ( $v ) || ($v instanceof \Traversable);
;
$isAssoc = function (array $arr): bool
// thanks to Mark Amery for this
if (array () === $arr)
return false;
return array_keys ( $arr ) !== range ( 0, count ( $arr ) - 1 );
;
$endsWith = function (string $haystack, string $needle): bool
// thanks to MrHus
$length = strlen ( $needle );
if ($length == 0)
return true;
return (substr ( $haystack, - $length ) === $needle);
;
$formatXML = function (string $xml) use ($endsWith): string
// there seems to be a bug with formatOutput on DOMDocuments that have used importNode with $deep=true
// on PHP 7.0.15...
$domd = new DOMDocument ( '1.0', 'UTF-8' );
$domd->preserveWhiteSpace = false;
$domd->formatOutput = true;
$domd->loadXML ( '<root>' . $xml . '</root>' );
$ret = trim ( $domd->saveXML ( $domd->getElementsByTagName ( "root" )->item ( 0 ) ) );
assert ( 0 === strpos ( $ret, '<root>' ) );
assert ( $endsWith ( $ret, '</root>' ) );
$full = trim ( substr ( $ret, strlen ( '<root>' ), - strlen ( '</root>' ) ) );
$ret = '';
// ... seems each line except the first line starts with 2 ugly spaces,
// presumably its the <root> element that starts with no spaces at all.
foreach ( explode ( "\n", $full ) as $line )
if (substr ( $line, 0, 2 ) === ' ')
$ret .= substr ( $line, 2 ) . "\n";
else
$ret .= $line . "\n";
$ret = trim ( $ret );
return $ret;
;
// $arr = new RecursiveArrayIterator ( $arr );
// $iterator = new RecursiveIteratorIterator ( $arr, RecursiveIteratorIterator::SELF_FIRST );
$iterator = $arr;
$domd = new DOMDocument ();
$root = $domd->createElement ( 'root' );
foreach ( $iterator as $key => $val )
// var_dump ( $key, $val );
$ele = $domd->createElement ( is_int ( $key ) ? $name_for_numeric_keys : $key );
if (! empty ( $val ) || $val === '0')
if ($is_iterable_compat ( $val ))
$asoc = $isAssoc ( $val );
$tmp = hhb_xml_encode ( $val, is_int ( $key ) ? $name_for_numeric_keys : $key );
// var_dump ( $tmp );
// die ();
$tmpDom = new DOMDocument();
@$tmpDom->loadXML ( '<root>' . $tmp . '</root>' );
foreach ( $tmpDom->getElementsByTagName ( "root" )->item ( 0 )->childNodes ?? [ ] as $tmp2 )
$tmp3 = $domd->importNode ( $tmp2, true );
if ($asoc)
$ele->appendChild ( $tmp3 );
else
$root->appendChild ( $tmp3 );
unset ( $tmp, $tmp2, $tmp3, $tmpDom );
if (! $asoc)
// echo 'REMOVING';die();
// $ele->parentNode->removeChild($ele);
continue;
else
$ele->textContent = $val;
$root->appendChild ( $ele );
$domd->preserveWhiteSpace = false;
$domd->formatOutput = true;
$ret = trim ( $domd->saveXML ( $root ) );
assert ( 0 === strpos ( $ret, '<root>' ) );
assert ( $endsWith ( $ret, '</root>' ) );
$ret = trim ( substr ( $ret, strlen ( '<root>' ), - strlen ( '</root>' ) ) );
// seems to be a bug with formatOutput on DOMDocuments that have used importNode with $deep=true..
$ret = $formatXML ( $ret );
return $ret;
【讨论】:
有点晚了,但是值得注意的是这里不包含doctype或者根元素,从而变成了格式不好的XML,可以将return $ret;
替换成return '<?xml version="1.0" encoding="UTF-8"?><root>' . $ret . '</root>';
“一年多之后,”我非常感谢您——以及随后的 Ben——分享了这段代码。它工作得很好。非常感谢你“救了我的培根”。 :-)【参考方案5】:
我的贡献:
function xml_encode(mixed $value=null, string $key="root", SimpleXMLElement $parent=null)
if(is_object($value)) $value = (array) $value;
if(!is_array($value))
if($parent === null)
if(is_numeric($key)) $key = 'item';
if($value===null) $node = new SimpleXMLElement("<$key />");
else $node = new SimpleXMLElement("<$key>$value</$key>");
else
$parent->addChild($key, $value);
$node = $parent;
else
$array_numeric = false;
if($parent === null)
if(empty($value)) $node = new SimpleXMLElement("<$key />");
else $node = new SimpleXMLElement("<$key></$key>");
else
if(!isset($value[0])) $node = $parent->addChild($key);
else
$array_numeric = true;
$node = $parent;
foreach( $value as $k => $v )
if($array_numeric) xml_encode($v, $key, $node);
else xml_encode($v, $k, $node);
return $node;
简单示例:
$a = "hello";
$xml_element = xml_encode($a,'a');
echo $xml_element->asXML();
空示例:
$xml_element = xml_encode(null,'example');
echo $xml_element->asXML();
复杂示例:
$w = new stdClass();
$w->special = true;
$w->name = 'Birthday Susan';
$v = new stdClass();
$v->name = 'John';
$v->surname = 'Smith';
$v->hobbies = array('soccer','cinema');
$v->job = 'policeman';
$v->events = new stdClass();
$v->events->tomorrow = false;
$v->events->yesterday = true;
$v->events->list = array($v->hobbies, $w);
$xml_element = xml_encode($v,'oembed');
echo $xml_element->asXML();
【讨论】:
【参考方案6】:这在大多数情况下对我有用:
$str = htmlentities($str , ENT_XML1);
文档: http://php.net/manual/en/function.htmlentities.php
【讨论】:
不支持数组,也不创建 xml 文件,它只是对单个字符串进行 xml 编码(将 转换为 >< 等) 我恭敬地同意这样的观点,即此响应与 OP 的情况确实无关,尽管它完全适合其预期的情况。但是,无论如何,谢谢。 如果你的 XML 结构已经生成,这其实是很方便的。以上是关于PHP中有没有像json_encode()这样的xml_encode()?的主要内容,如果未能解决你的问题,请参考以下文章
PHP - json_encode(string, JSON_UNESCAPED_UNICODE) 不转义捷克字符