PHP中有像json_encode()这样的xml_encode()吗?

时间:2023-01-30 23:15:12

In PHP it is easy to pass back an json objects by using the json_encode().
However is there an XML equivalent of this?

在PHP中,很容易通过使用json_encode()传递json对象。然而,是否存在与之对应的XML呢?

5 个解决方案

#1


8  

JSON can express php arrays, integers, strings, etc. natively. XML has no such concepts - just elements, attributes, and text. If you want to transfer an object verbatim, use JSON. If you want to implement a complex API, use XML, for example the php DOM interface.

JSON可以直接表示php数组、整数、字符串等。XML没有这样的概念——只有元素、属性和文本。如果希望逐字传输对象,请使用JSON。如果希望实现复杂的API,请使用XML,例如php DOM接口。

#2


7  

You can define your own xml_encode() function such as this the one from http://darklaunch.com/2009/05/23/php-xml-encode-using-domdocument-convert-array-to-xml-json-encode

您可以定义您自己的xml_encode()函数,比如http://darklaunch.com/2009/05/23/php-xml-encode- use -domdocument-convert- arrayto -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));
        }
    }
}

#3


4  

You could use xmlrpc_encode.

您可以使用xmlrpc_encode。

 xmlrpc_encode ($your_array);

Be careful because this function is EXPERIMENTAL.

要小心,因为这个函数是实验性的。

Reference: http://php.net/manual/en/function.xmlrpc-encode.php

参考:http://php.net/manual/en/function.xmlrpc-encode.php

#4


1  

here is one for php7.0+ , i bet it is far from optimal , the code is non-trivial, and it has NOT been tested much, but at least it works for my data (unlike Seph's code)...

这里是php7.0+的一种,我打赌它不是最优的,代码是不平凡的,它还没有经过很多测试,但是至少它对我的数据起作用(不像Seph的代码)……

example:

例子:

$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 ));

output:

输出:

<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&lt;special&gt;characters&amp;test</special>
<me_n_you>true</me_n_you>

function: - Edit: fixed a bug with encoding empty arrays.

函数:-编辑:修正一个编码空数组的错误。

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 ();
                $tmp = @DOMDocument::loadXML ( '<root>' . $tmp . '</root>' );
                foreach ( $tmp->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 );
                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;
}

#5


-2  

This works for me in most cases:

这在大多数情况下对我都适用:

$str = htmlentities($str , ENT_XML1);

Docs: http://php.net/manual/en/function.htmlentities.php

文档:http://php.net/manual/en/function.htmlentities.php

#1


8  

JSON can express php arrays, integers, strings, etc. natively. XML has no such concepts - just elements, attributes, and text. If you want to transfer an object verbatim, use JSON. If you want to implement a complex API, use XML, for example the php DOM interface.

JSON可以直接表示php数组、整数、字符串等。XML没有这样的概念——只有元素、属性和文本。如果希望逐字传输对象,请使用JSON。如果希望实现复杂的API,请使用XML,例如php DOM接口。

#2


7  

You can define your own xml_encode() function such as this the one from http://darklaunch.com/2009/05/23/php-xml-encode-using-domdocument-convert-array-to-xml-json-encode

您可以定义您自己的xml_encode()函数,比如http://darklaunch.com/2009/05/23/php-xml-encode- use -domdocument-convert- arrayto -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));
        }
    }
}

#3


4  

You could use xmlrpc_encode.

您可以使用xmlrpc_encode。

 xmlrpc_encode ($your_array);

Be careful because this function is EXPERIMENTAL.

要小心,因为这个函数是实验性的。

Reference: http://php.net/manual/en/function.xmlrpc-encode.php

参考:http://php.net/manual/en/function.xmlrpc-encode.php

#4


1  

here is one for php7.0+ , i bet it is far from optimal , the code is non-trivial, and it has NOT been tested much, but at least it works for my data (unlike Seph's code)...

这里是php7.0+的一种,我打赌它不是最优的,代码是不平凡的,它还没有经过很多测试,但是至少它对我的数据起作用(不像Seph的代码)……

example:

例子:

$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 ));

output:

输出:

<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&lt;special&gt;characters&amp;test</special>
<me_n_you>true</me_n_you>

function: - Edit: fixed a bug with encoding empty arrays.

函数:-编辑:修正一个编码空数组的错误。

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 ();
                $tmp = @DOMDocument::loadXML ( '<root>' . $tmp . '</root>' );
                foreach ( $tmp->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 );
                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;
}

#5


-2  

This works for me in most cases:

这在大多数情况下对我都适用:

$str = htmlentities($str , ENT_XML1);

Docs: http://php.net/manual/en/function.htmlentities.php

文档:http://php.net/manual/en/function.htmlentities.php