我正在尝试将xml中的xml转换为json。如果我使用简单的xml和json_encode进行简单的转换,则xml show中没有任何属性。

$xml = simplexml_load_file("states.xml");
echo json_encode($xml);


所以我试图像这样手动解析它。 />
foreach($xml->children() as $state)
{
    $states[]= array('state' => $state->name); 
}       
echo json_encode($states);


,状态输出是{"state":{"0":"Alabama"}}而不是{"state":"Alabama"}

我在做什么错?

XML:

<?xml version="1.0" ?>
<states>
    <state id="AL">     
    <name>Alabama</name>
    </state>
    <state id="AK">
        <name>Alaska</name>
    </state>
</states>


输出:

[{"state":{"0":"Alabama"}},{"state":{"0":"Alaska"}


var dump:

object(SimpleXMLElement)#1 (1) {
["state"]=>
array(2) {
[0]=>
object(SimpleXMLElement)#3 (2) {
  ["@attributes"]=>
  array(1) {
    ["id"]=>
    string(2) "AL"
  }
  ["name"]=>
  string(7) "Alabama"
}
[1]=>
object(SimpleXMLElement)#2 (2) {
  ["@attributes"]=>
  array(1) {
    ["id"]=>
    string(2) "AK"
  }
  ["name"]=>
  string(6) "Alaska"
}
}
}


评论

请提供XML的摘要以及解析后的最终数组结构。 (var_dump可以正常工作。)

添加了输入,输出和var_dump

某些应用程序需要“ perfec XML到JSON映射”,即jsonML,请参见此处的解决方案。

#1 楼

来自XML的Json&Array来自3行:

$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);


评论


此解决方案并非完美无缺。它完全放弃了XML属性。因此, John 被解释为 John

–杰克·威尔逊(Jake Wilson)
15年1月26日在19:57

$ xml = simplexml_load_string($ xml_string,'SimpleXMLElement',LIBXML_NOCDATA);展平cdata元素。

–txyoji
15年7月14日在17:29

@JakeWilson也许已经过去了两年,并且进行了各种版本修复,但是在PHP 5.6.30上,此方法将产生所有数据。属性存储在@attributes键下的数组中,因此它可以完美无瑕,美观地工作。 3行短代码可以很好地解决我的问题。

–AlexanderMP
17年2月7日在16:12

如果您有多个名称空间,则无法使用,只能选择一个名称空间,该名称空间将传递到$ json_string:'(

– Jirislav
17年11月26日在5:49

请记住,使用此解决方案时,当可能有多个具有相同名称的节点时,一个节点将导致键仅指向一个元素,但是多个节点将导致键指向元素的数组: 123 456 123 -> {“ item”:[{“ a “:[” 123“,” 456“]},{” a“:” 123“}]}。 ratfactor在php.net上提供的解决方案通过始终将元素存储在数组中来解决该问题。

– Klesun
19年1月7日在21:44

#2 楼

很抱歉回答一个旧帖子,但是本文概述了一种相对简短,简洁且易于维护的方法。我自己进行了测试,效果很好。

http://lostechies.com/seanbiefeld/2011/10/21/simple-xml-to-json-with-php/

<?php   
class XmlToJson {
    public function Parse ($url) {
        $fileContents= file_get_contents($url);
        $fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);
        $fileContents = trim(str_replace('"', "'", $fileContents));
        $simpleXml = simplexml_load_string($fileContents);
        $json = json_encode($simpleXml);

        return $json;
    }
}
?>


评论


如果您的XML中有多个相同标签的实例,则此方法将不起作用,而json_encode最终只会序列化标签的最后一个实例。

–ethree
13年7月7日在20:50

#3 楼

我想到了。 json_encode处理对象的方式与处理字符串不同。我将该对象转换为字符串,现在可以使用。

foreach($xml->children() as $state)
{
    $states[]= array('state' => (string)$state->name); 
}       
echo json_encode($states);


#4 楼

我想我参加聚会有点晚了,但是我写了一个小函数来完成这项任务。它还照顾属性,文本内容,即使具有相同节点名称的多个节点都是同级节点。

免责声明:
我不是PHP本地人,所以请简单一点错误。

function xml2js($xmlnode) {
    $root = (func_num_args() > 1 ? false : true);
    $jsnode = array();

    if (!$root) {
        if (count($xmlnode->attributes()) > 0){
            $jsnode["$"] = array();
            foreach($xmlnode->attributes() as $key => $value)
                $jsnode["$"][$key] = (string)$value;
        }

        $textcontent = trim((string)$xmlnode);
        if (count($textcontent) > 0)
            $jsnode["_"] = $textcontent;

        foreach ($xmlnode->children() as $childxmlnode) {
            $childname = $childxmlnode->getName();
            if (!array_key_exists($childname, $jsnode))
                $jsnode[$childname] = array();
            array_push($jsnode[$childname], xml2js($childxmlnode, true));
        }
        return $jsnode;
    } else {
        $nodename = $xmlnode->getName();
        $jsnode[$nodename] = array();
        array_push($jsnode[$nodename], xml2js($xmlnode, true));
        return json_encode($jsnode);
    }
}   


用法示例:

$xml = simplexml_load_file("myfile.xml");
echo xml2js($xml);


示例输入(myfile.xml):

<family name="Johnson">
    <child name="John" age="5">
        <toy status="old">Trooper</toy>
        <toy status="old">Ultrablock</toy>
        <toy status="new">Bike</toy>
    </child>
</family>


示例输出:

{"family":[{"$":{"name":"Johnson"},"child":[{"$":{"name":"John","age":"5"},"toy":[{"$":{"status":"old"},"_":"Trooper"},{"$":{"status":"old"},"_":"Ultrablock"},{"$":{"status":"new"},"_":"Bike"}]}]}]}


漂亮的打印件:

{
    "family" : [{
            "$" : {
                "name" : "Johnson"
            },
            "child" : [{
                    "$" : {
                        "name" : "John",
                        "age" : "5"
                    },
                    "toy" : [{
                            "$" : {
                                "status" : "old"
                            },
                            "_" : "Trooper"
                        }, {
                            "$" : {
                                "status" : "old"
                            },
                            "_" : "Ultrablock"
                        }, {
                            "$" : {
                                "status" : "new"
                            },
                            "_" : "Bike"
                        }
                    ]
                }
            ]
        }
    ]
}


要记住的怪癖:
几个具有相同标记名的标记可能是同级标记。除了最后一个兄弟,其他解决方案很可能会丢弃所有其他兄弟。为了避免这种情况,即使每个节点只有一个孩子,也要使用一个数组,该数组为标记名的每个实例保存一个对象。 (请参见示例中的多个“”元素)

即使根元素(在有效XML文档中应该只存在一个根元素)也与实例的对象一起存储为数组,只是为了获得一致的数据结构。

为了能够区分XML节点内容和XML属性,每个对象属性都存储在“ $”子对象中,内容存储在“ _”子对象中。

编辑:
我忘记显示示例输入数据的输出

{
    "states" : [{
            "state" : [{
                    "$" : {
                        "id" : "AL"
                    },
                    "name" : [{
                            "_" : "Alabama"
                        }
                    ]
                }, {
                    "$" : {
                        "id" : "AK"
                    },
                    "name" : [{
                            "_" : "Alaska"
                        }
                    ]
                }
            ]
        }
    ]
}


评论


它可以解析大型XML数据吗?

– Volatil3
16年1月1日在18:09

此解决方案更好,因为不丢弃XML属性。另请参见xml.com/lpt/a/1658(请参阅“半结构化XML”),以了解为什么这种复杂结构比简化结构更好。....对于CDATA,操作@txyoji建议将CDATA元素$ xml展平= simplexml_load_file(“ myfile.xml”,'SimpleXMLElement',LIBXML_NOCDATA); 。

– Peter Krauss
16-10-6在4:27



非常感谢您的自定义功能!它使调整非常容易。顺便说一句,添加了函数的编辑版本,该版本以JS方式解析XML:每个条目都有自己的对象(如果条目具有相同的标记名,则条目不会存储在单个数组中),因此顺序得以保留。

–lucifer63
19年11月6日在11:16

错误致命错误:未捕获错误:在bool上调用成员函数getName()..我认为版本php失败:-( ..请帮助!

– KingRider
19年11月26日在11:23

#5 楼

一个常见的陷阱是忘记json_encode()不尊重具有textvalue和attribute的元素。它将选择其中之一,这意味着数据丢失。
以下功能解决了该问题。如果决定采用json_encode / decode方式,则建议使用以下功能。

function json_prepare_xml($domNode) {
  foreach($domNode->childNodes as $node) {
    if($node->hasChildNodes()) {
      json_prepare_xml($node);
    } else {
      if($domNode->hasAttributes() && strlen($domNode->nodeValue)){
         $domNode->setAttribute("nodeValue", $node->textContent);
         $node->nodeValue = "";
      }
    }
  }
}

$dom = new DOMDocument();
$dom->loadXML( file_get_contents($xmlfile) );
json_prepare_xml($dom);
$sxml = simplexml_load_string( $dom->saveXML() );
$json = json_decode( json_encode( $sxml ) );


这样,<foo bar="3">Lorem</foo>不会在JSON中最终成为{"foo":"Lorem"}

评论


如果纠正了语法错误,则不会编译并且不会产生描述的输出。

–理查德·基弗(Richard Kiefer)
15年1月21日在10:36

什么是$ dom?那个是从哪里来的?

–杰克·威尔逊(Jake Wilson)
15年1月26日在20:20

$ dom =新的DOMDocument();是它来自哪里

–斯科特
15年11月25日在21:28

最后一行代码:$ json = json_decode(json_encode($ sxml)));应该是:$ json = json_decode(json_encode($ sxml));

–查理·史密斯
16-2-29在2:46



#6 楼

尝试使用此库

$xml = ... // Xml file data

// first approach
$Json = json_encode(simplexml_load_string($xml));

---------------- OR -----------------------

// second approach
$Json = json_encode(simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA));

echo $Json;




您可以使用以下库:https://github.com/rentpost/xml2array

#7 楼

为此,我使用了Miles Johnson的TypeConverter。它可以使用Composer进行安装。

您可以使用它编写如下内容:

<?php
require 'vendor/autoload.php';
use mjohnson\utility\TypeConverter;

$xml = file_get_contents("file.xml");
$arr = TypeConverter::xmlToArray($xml, TypeConverter::XML_GROUP);
echo json_encode($arr);


#8 楼

优化Antonio Max答案:

$xmlfile = 'yourfile.xml';
$xmlparser = xml_parser_create();

// open a file and read data
$fp = fopen($xmlfile, 'r');
//9999999 is the length which fread stops to read.
$xmldata = fread($fp, 9999999);

// converting to XML
$xml = simplexml_load_string($xmldata, "SimpleXMLElement", LIBXML_NOCDATA);

// converting to JSON
$json = json_encode($xml);
$array = json_decode($json,TRUE);


评论


我使用了这种方法,但是JSON为空。 XML有效。

–ryabenko-pro
18年1月9日在19:07

#9 楼

像护身符一样工作的最佳解决方案

$fileContents= file_get_contents($url);

$fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);

$fileContents = trim(str_replace('"', "'", $fileContents));

$simpleXml = simplexml_load_string($fileContents);

//$json = json_encode($simpleXml); // Remove // if you want to store the result in $json variable

echo '<pre>'.json_encode($simpleXml,JSON_PRETTY_PRINT).'</pre>';


来源

#10 楼

如果您只想将XML的特定部分转换为JSON,则可以使用XPath检索并将其转换为JSON。

<?php
$file = @file_get_contents($xml_File, FILE_TEXT);
$xml = new SimpleXMLElement($file);
$xml_Excerpt = @$xml->xpath('/states/state[@id="AL"]')[0]; // [0] gets the node
echo json_encode($xml_Excerpt);
?>


请注意,如果您的Xpath错误,将因错误而死亡。因此,如果您要通过AJAX调用进行调试,建议您也记录响应正文。

#11 楼

此解决方案处理名称空间,属性,并通过重复元素(即使只有一次出现,也始终在数组中)产生一致的结果。
受ratfactor的sxiToArray()启发。

/**
 * <root><a>5</a><b>6</b><b>8</b></root> -> {"root":[{"a":["5"],"b":["6","8"]}]}
 * <root a="5"><b>6</b><b>8</b></root> -> {"root":[{"a":"5","b":["6","8"]}]}
 * <root xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"><a>123</a><wsp:b>456</wsp:b></root> 
 *   -> {"root":[{"xmlns:wsp":"http://schemas.xmlsoap.org/ws/2004/09/policy","a":["123"],"wsp:b":["456"]}]}
 */
function domNodesToArray(array $tags, \DOMXPath $xpath)
{
    $tagNameToArr = [];
    foreach ($tags as $tag) {
        $tagData = [];
        $attrs = $tag->attributes ? iterator_to_array($tag->attributes) : [];
        $subTags = $tag->childNodes ? iterator_to_array($tag->childNodes) : [];
        foreach ($xpath->query('namespace::*', $tag) as $nsNode) {
            // the only way to get xmlns:*, see https://stackoverflow.com/a/2470433/2750743
            if ($tag->hasAttribute($nsNode->nodeName)) {
                $attrs[] = $nsNode;
            }
        }

        foreach ($attrs as $attr) {
            $tagData[$attr->nodeName] = $attr->nodeValue;
        }
        if (count($subTags) === 1 && $subTags[0] instanceof \DOMText) {
            $text = $subTags[0]->nodeValue;
        } elseif (count($subTags) === 0) {
            $text = '';
        } else {
            // ignore whitespace (and any other text if any) between nodes
            $isNotDomText = function($node){return !($node instanceof \DOMText);};
            $realNodes = array_filter($subTags, $isNotDomText);
            $subTagNameToArr = domNodesToArray($realNodes, $xpath);
            $tagData = array_merge($tagData, $subTagNameToArr);
            $text = null;
        }
        if (!is_null($text)) {
            if ($attrs) {
                if ($text) {
                    $tagData['_'] = $text;
                }
            } else {
                $tagData = $text;
            }
        }
        $keyName = $tag->nodeName;
        $tagNameToArr[$keyName][] = $tagData;
    }
    return $tagNameToArr;
}

function xmlToArr(string $xml)
{
    $doc = new \DOMDocument();
    $doc->loadXML($xml);
    $xpath = new \DOMXPath($doc);
    $tags = $doc->childNodes ? iterator_to_array($doc->childNodes) : [];
    return domNodesToArray($tags, $xpath);
}


示例:

php > print(json_encode(xmlToArr('<root a="5"><b>6</b></root>')));
{"root":[{"a":"5","b":["6"]}]}


评论


这实际上适用于多名称空间的情况,比其他解决方案要好,为什么要投反对票?

–aaron
7月10日4:00

#12 楼

This is better solution

$fileContents= file_get_contents("https://www.feedforall.com/sample.xml");
$fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);
$fileContents = trim(str_replace('"', "'", $fileContents));
$simpleXml = simplexml_load_string($fileContents);
$json = json_encode($simpleXml);
$array = json_decode($json,TRUE);
return $array;


#13 楼

这是对安东尼奥·马克斯(Antonio Max)最推崇的解决方案的改进,该解决方案也与具有名称空间的XML一起使用(通过用下划线替换冒号)。它还具有一些其他选项(并且可以正确解析<person my-attribute='name'>John</person>)。

 function parse_xml_into_array($xml_string, $options = array()) {
    /*
    DESCRIPTION:
    - parse an XML string into an array
    INPUT:
    - $xml_string
    - $options : associative array with any of these keys:
        - 'flatten_cdata' : set to true to flatten CDATA elements
        - 'use_objects' : set to true to parse into objects instead of associative arrays
        - 'convert_booleans' : set to true to cast string values 'true' and 'false' into booleans
    OUTPUT:
    - associative array
    */

    // Remove namespaces by replacing ":" with "_"
    if (preg_match_all("|</([\w\-]+):([\w\-]+)>|", $xml_string, $matches, PREG_SET_ORDER)) {
        foreach ($matches as $match) {
            $xml_string = str_replace('<'. $match[1] .':'. $match[2], '<'. $match[1] .'_'. $match[2], $xml_string);
            $xml_string = str_replace('</'. $match[1] .':'. $match[2], '</'. $match[1] .'_'. $match[2], $xml_string);
        }
    }

    $output = json_decode(json_encode(@simplexml_load_string($xml_string, 'SimpleXMLElement', ($options['flatten_cdata'] ? LIBXML_NOCDATA : 0))), ($options['use_objects'] ? false : true));

    // Cast string values "true" and "false" to booleans
    if ($options['convert_booleans']) {
        $bool = function(&$item, $key) {
            if (in_array($item, array('true', 'TRUE', 'True'), true)) {
                $item = true;
            } elseif (in_array($item, array('false', 'FALSE', 'False'), true)) {
                $item = false;
            }
        };
        array_walk_recursive($output, $bool);
    }

    return $output;
}
 


评论


除非它是具有琐碎结构和非常可预测的数据的简单XML,否则不要使用Regex来解析XML。我不能强调这个解决方案有多糟糕。这会破坏数据。更不用说它是如此之慢(您使用正则表达式进行解析,然后再次进行解析?)并且不处理自闭标签。

–AlexanderMP
17年2月7日在16:19

我认为您不是真的在看这个功能。它不使用regex进行实际的解析,只是作为处理名称空间的简单解决方案-它已经在我所有的xml案例中都适用-并且它正在运行是最重要的,而不是“从政治上来说是正确的”。不过,欢迎您根据需要进行改进!

– TheStoryCoder
17年2月13日在21:39

它对您有用的事实并不意味着它是对的。像这样的代码会生成难以诊断的错误并产生漏洞。我的意思是即使只是在类似w3schools.com/xml/xml_elements.asp这样的站点上简单地查看XML规范,也显示出了该解决方案不起作用的许多原因。就像我说的那样,它无法检测到之类的自闭标签,也无法解决XML允许的以开头或包含下划线的元素。无法检测到CDATA。正如我所说的,它很慢。由于内部解析,这是O(n ^ 2)的复杂度。

–AlexanderMP
17年5月9日17:41

事实是,这里甚至没有要求处理名称空间,并且有适当的方式来处理名称空间。命名空间作为一种有用的构造而存在,不能像这样进行解析,并且会变成可憎的东西,任何合理的解析器都不会对其进行处理。为此,您所需要做的并不是创建“ 2016年最慢算法”奖的竞争者,而是要做一些搜索,以提出各种实际解决方案,例如stackoverflow.com/ questions / 16412047 /…并且称此为改进?哇。

–AlexanderMP
17年5月9日在17:48



#14 楼

发现FTav的答案非常有用,因为它非常可定制,但是他的xml2js函数存在一些缺陷。例如,如果子元素具有相同的标记名,它们将全部存储在单个对象中,这意味着将不保留元素的顺序。在某些情况下,我们确实希望保留顺序,因此我们最好将每个元素的数据存储在单独的对象中:

 function xml2js($xmlnode) {
    $jsnode = array();
    $nodename = $xmlnode->getName();
    $current_object = array();

    if (count($xmlnode->attributes()) > 0) {
        foreach($xmlnode->attributes() as $key => $value) {
            $current_object[$key] = (string)$value;
        }
    }

    $textcontent = trim((string)$xmlnode);
    if (strlen($textcontent) > 0) {
        $current_object["content"] = $textcontent;
    }

    if (count($xmlnode->children()) > 0) {
        $current_object['children'] = array();
        foreach ($xmlnode->children() as $childxmlnode) {
            $childname = $childxmlnode->getName();
            array_push($current_object['children'], xml2js($childxmlnode, true));
        }
    }

    $jsnode[ $nodename ] = $current_object;
    return $jsnode;
}
 


这是它的工作方式。初始xml结构:

<some-tag some-attribute="value of some attribute">
  <another-tag>With text</another-tag>
  <surprise></surprise>
  <another-tag>The last one</another-tag>
</some-tag>


结果JSON:

{
    "some-tag": {
        "some-attribute": "value of some attribute",
        "children": [
            {
                "another-tag": {
                    "content": "With text"
                }
            },
            {
                "surprise": []
            },
            {
                "another-tag": {
                    "content": "The last one"
                }
            }
        ]
    }
}


#15 楼

这里的所有解决方案都有问题!

...当表示形式需要完美的XML解释(属性没有问题)并再现所有text-tag-text-tag-text -...的顺序时标签。还要记住这里的JSON对象是“无序集合”(不是重复键,并且键不能具有预定义的顺序)...甚至ZF的xml2json也都是错误的(!),因为不能完全保留XML结构。

这里的所有解决方案都有这种简单XML的问题,

     <states x-x='1'>
        <state y="123">Alabama</state>
        My name is <b>John</b> Doe
        <state>Alaska</state>
    </states>
 


。 @FTav解决方案似乎比三行解决方案要好,但是使用此XML进行测试时也几乎没有错误。

旧的解决方案是最好的(用于无损表示)

该解决方案,今天众所周知的jsonML,已由Zorba专案和其他组织使用,最初由Stephen McKamey和John Snelson分别于〜2006或〜2007提出。

 // the core algorithm is the XSLT of the "jsonML conventions"
// see  https://github.com/mckamey/jsonml
$xslt = 'https://raw.githubusercontent.com/mckamey/jsonml/master/jsonml.xslt';
$dom = new DOMDocument;
$dom->loadXML('
    <states x-x=\'1\'>
        <state y="123">Alabama</state>
        My name is <b>John</b> Doe
        <state>Alaska</state>
    </states>
');
if (!$dom) die("\nERROR!");
$xslDoc = new DOMDocument();
$xslDoc->load($xslt);
$proc = new XSLTProcessor();
$proc->importStylesheet($xslDoc);
echo $proc->transformToXML($dom);
 


产品

 ["states",{"x-x":"1"},
    "\n\t    ",
    ["state",{"y":"123"},"Alabama"],
    "\n\t\tMy name is ",
    ["b","John"],
    " Doe\n\t    ",
    ["state","Alaska"],
    "\n\t"
]
 


请参见http://jsonML.org或github.com/mckamey/jsonml。此JSON的生产规则基于JSON-analog元素,



此语法是元素定义和重复,带有element-list ::= element ',' element-list | element

评论


我怀疑非常现实的用例会出现非常不寻常的xml结构。

– TheStoryCoder
17年2月13日在21:49

#16 楼

在研究了所有答案之后,我想出了一个解决方案,该解决方案可以在浏览器(包括控制台/开发工具)中与我的JavaScript函数配合使用:

<?php

 // PHP Version 7.2.1 (Windows 10 x86)

 function json2xml( $domNode ) {
  foreach( $domNode -> childNodes as $node) {
   if ( $node -> hasChildNodes() ) { json2xml( $node ); }
   else {
    if ( $domNode -> hasAttributes() && strlen( $domNode -> nodeValue ) ) {
     $domNode -> setAttribute( "nodeValue", $node -> textContent );
     $node -> nodeValue = "";
    }
   }
  }
 }

 function jsonOut( $file ) {
  $dom = new DOMDocument();
  $dom -> loadXML( file_get_contents( $file ) );
  json2xml( $dom );
  header( 'Content-Type: application/json' );
  return str_replace( "@", "", json_encode( simplexml_load_string( $dom -> saveXML() ), JSON_PRETTY_PRINT ) );
 }

 $output = jsonOut( 'https://boxelizer.com/assets/a1e10642e9294f39/b6f30987f0b66103.xml' );

 echo( $output );

 /*
  Or simply 
  echo( jsonOut( 'https://boxelizer.com/assets/a1e10642e9294f39/b6f30987f0b66103.xml' ) );
 */

?>


它基本上会创建一个新的DOMDocument,并在其中加载XML文件,并遍历每个节点和子节点,以获取数据/参数并将其导出为JSON,而不会出现烦人的“ @”符号。

链接到XML文件。

#17 楼

如果XML是Soap文件,则可以使用此文件:
$xmlStr = preg_replace("/(<\/?)(\w+):([^>]*>)/", "", $xmlStr);
$xml = new SimpleXMLElement($xmlStr);
return json_encode($xml);


#18 楼

        $content = str_replace(array("\n", "\r", "\t"), '', $response);
        $content = trim(str_replace('"', "'", $content));
        $xml = simplexml_load_string($content);
        $json = json_encode($xml);
        return json_decode($json,TRUE);

这对我有用

#19 楼

从以下来源得到接受的(antonio)答案:
<MyData>
  <Level1 myRel="parent" myName="AAA">
    <Level2 myRel="child1" myName="BBB">
    <Level2 myRel="child2" myName="CCC">
      ...

您将得到类似以下的数组:
  'Level1' =>
  [
      0 =>
      [
          '@attributes' => 
          [
              'myRel' => 'parent'
              'myName'  => 'AAA'
          ],
          'Level2' => 
          [
              0 => 
              [
                  '@attributes' => 
                  [
                      'myRel'  => 'child_1'
                      'myName'   => 'BBB'
                  ],

因此,如果要使用键配对数组(而不是0数字),使用您选择的密钥,即myName
  'Level1' =>
  [
      'AAA' =>
      [
          '@attributes' => 
          [
              'myRel' => 'parent'
              'myName'  => 'AAA'
          ],
          'Level2' => 
          [
              'BBB' => 
              [
                  '@attributes' => 
                  [
                      'myRel'  => 'child_1'
                      'myName'   => 'BBB'
                  ],

,然后使用xmlToArrayByKey($xmlContent, 'myName')。代码在这里:
public function xmlToArrayByKey($content, $keyName)
{
    try
    {
        $xml = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA );
        $array= json_decode( json_encode($xml), TRUE);
        return $this->xmlSetChild($array, $keyName);
    } catch (Exception $ex) {
        return ['xmlerror'=>$ex];
    }
}

public function xmlSetChild($array, $keyName, $step=0)
{
    $new_array= [];
    foreach ($array as $key_1=>$value_1)
    {
        if (is_array($value_1) && isset($value_1[0]))
        {
            foreach ($value_1 as $idx=>$value_2)
            {
                $keyValue = $value_2['@attributes'][$keyName];
                $new_array[$key_1][$keyValue] = $this->xmlSetChild($value_2, $keyName, $step+1);
            }
        }
        else{
            $new_array[$key_1]=$value_1;
        }
    }
    return $new_array;
}


#20 楼

看起来$state->name变量持有一个数组。您可以在foreach内使用

var_dump($state)


进行测试。

可以的话,可以将foreach内的行更改为

$states[]= array('state' => array_shift($state->name)); 


进行更正。

评论


看起来属性是数组,而不是$ state-> name

–布莱恩·哈德洛克(Bryan Hadlock)
2012年1月12日下午6:11

#21 楼

$templateData =  $_POST['data'];

// initializing or creating array
$template_info =  $templateData;

// creating object of SimpleXMLElement
$xml_template_info = new SimpleXMLElement("<?xml version=\"1.0\"?><template></template>");

// function call to convert array to xml
array_to_xml($template_info,$xml_template_info);

//saving generated xml file
 $xml_template_info->asXML(dirname(__FILE__)."/manifest.xml") ;

// function defination to convert array to xml
function array_to_xml($template_info, &$xml_template_info) {
    foreach($template_info as $key => $value) {
        if(is_array($value)) {
            if(!is_numeric($key)){
                $subnode = $xml_template_info->addChild($key);
                if(is_array($value)){
                    $cont = 0;
                    foreach(array_keys($value) as $k){
                        if(is_numeric($k)) $cont++;
                    }
                }

                if($cont>0){
                    for($i=0; $i < $cont; $i++){
                        $subnode = $xml_body_info->addChild($key);
                        array_to_xml($value[$i], $subnode);
                    }
                }else{
                    $subnode = $xml_body_info->addChild($key);
                    array_to_xml($value, $subnode);
                }
            }
            else{
                array_to_xml($value, $xml_template_info);
            }
        }
        else {
            $xml_template_info->addChild($key,$value);
        }
    }
}


评论


这是一个基于数据数组的小型通用解决方案,可以是JSON转换的json_decode ... lucky

–八达通(Octavio)Perez Gallegos
16年6月30日在22:45



这以什么方式回答了原始问题?您的答案似乎比原始问题更复杂,而且似乎甚至都没有提到JSON。

– Dan R
16年6月30日在22:54

#22 楼

如果您是ubuntu用户,请安装xml阅读器(我有php 5.6。如果您有其他文件,请找到软件包并进行安装)

sudo apt-get install php5.6-xml
service apache2 restart

$fileContents = file_get_contents('myDirPath/filename.xml');
$fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);
$fileContents = trim(str_replace('"', "'", $fileContents));
$oldXml = $fileContents;
$simpleXml = simplexml_load_string($fileContents);
$json = json_encode($simpleXml);