在PHP中是否有类似json_encode()的xml_encode()?

时间:2011-09-30 10:28:56

标签: php xml ajax

在PHP中,使用json_encode()很容易传回json对象 但是有一个与此类似的XML吗?

6 个答案:

答案 0 :(得分:8)

您可以定义自己的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));
        }
    }
}

答案 1 :(得分:7)

JSON本身可以表达php数组,整数,字符串等。 XML没有这样的概念 - 只是元素,属性和文本。如果要逐字传输对象,请使用JSON。如果要实现复杂的API,请使用XML,例如php DOM interface

答案 2 :(得分:5)

您可以使用xmlrpc_encode

 xmlrpc_encode ($your_array);

小心,因为这个功能是实验性的。

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

答案 3 :(得分:1)

这里有一个用于php7.0 +,我敢打赌它远非最佳,代码非常重要,并且 NOT 已经过多次测试,但至少它适用于我的数据(与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&lt;special&gt;characters&amp;test</special>
<me_n_you>true</me_n_you>

功能: - 编辑:修复了编码空数组的错误。

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;
}

答案 4 :(得分:0)

我的贡献:

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

答案 5 :(得分:-3)

在大多数情况下,这对我有用:

$str = htmlentities($str , ENT_XML1);

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