array
"item3.1" =>"3.1",
"item3.2" =>"3"/>

将PHP关联数组与XML相互传递

将PHP关联数组与XML相互传递

Passing PHP associative arrays to and from XML

是否有一种简单的方法可以将PHP关联数组与XML进行封送处理? 例如,我有以下数组:

1
2
3
4
5
6
7
$items = array("1","2",
    array(
       "item3.1" =>"3.1",
       "item3.2" =>"3.2"
       "isawesome" => true
    )
);

如何在尽可能少的行中将其转换为类似于以下XML的内容,然后再次返回?

1
2
3
4
5
6
7
8
9
<items>
    <item>1</item>
    <item>2</item>
    <item>
        <item3_1>3.1</item3_1>
        <item3_2>3.2</item3_2>
        <isawesome>true</isawesome>
    </item>
</items>

我真的不在乎是否需要稍微更改数组结构,或者输出的XML是否与上面的示例不同。 我一直在尝试使用PHP的XMLReader和XMLWriter,但是文档非常糟糕,因此生成的代码看起来与我的感觉不一样:

1
2
$xml = SomeXMLWriter::writeArrayToXml($items);
$array = SomeXMLWriter::writeXmlToArray($xml);

在没有编写自己的自定义类的情况下,获取PHP数组的基本原始XML转储真的比这难吗?

我尽量避免梨。 除了配置方面的麻烦之外,我从未使用过使用过的任何软件包。


SimpleXML非常适合您使用。


对于那些不使用PEAR软件包但已安装PHP5的用户。这为我工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/**
 * Build A XML Data Set
 *
 * @param array $data Associative Array containing values to be parsed into an XML Data Set(s)
 * @param string $startElement Root Opening Tag, default fx_request
 * @param string $xml_version XML Version, default 1.0
 * @param string $xml_encoding XML Encoding, default UTF-8
 * @return string XML String containig values
 * @return mixed Boolean false on failure, string XML result on success
 */

public function buildXMLData($data, $startElement = 'fx_request', $xml_version = '1.0', $xml_encoding = 'UTF-8') {
    if(!is_array($data)) {
        $err = 'Invalid variable type supplied, expected array not found on line '.__LINE__." in Class:".__CLASS__." Method:".__METHOD__;
        trigger_error($err);
        if($this->_debug) echo $err;
        return false; //return false error occurred
    }
    $xml = new XmlWriter();
    $xml->openMemory();
    $xml->startDocument($xml_version, $xml_encoding);
    $xml->startElement($startElement);

    /**
     * Write XML as per Associative Array
     * @param object $xml XMLWriter Object
     * @param array $data Associative Data Array
     */

     function write(XMLWriter $xml, $data) {
         foreach($data as $key => $value) {
             if(is_array($value)) {
                 $xml->startElement($key);
                 write($xml, $value);
                 $xml->endElement();
                 continue;
             }
             $xml->writeElement($key, $value);
         }
     }
     write($xml, $data);

     $xml->endElement();//write end element
     //Return the XML results
     return $xml->outputMemory(true);
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Xml {

    public static function from_array($arr, $xml = NULL)
    {
        $first = $xml;
        if($xml === NULL) $xml = new SimpleXMLElement('<root/>');
        foreach ($arr as $k => $v)
        {
            is_array($v)
                ? self::from_array($v, $xml->addChild($k))
                : $xml->addChild($k, $v);
        }
        return ($first === NULL) ? $xml->asXML() : $xml;
    }

    public static function to_array($xml)
    {
        $xml = simplexml_load_string($xml);
        $json = json_encode($xml);
        return json_decode($json,TRUE);
    }

}

$xml = xml::from_array($array);
$array = xml::to_array($xml);

我遇到了一些相同的问题,因此我创建了两个类:

BXML

扩展SimpleXml并更正其某些问题的类。就像无法添加CData节点或Comment节点一样。我还添加了一些其他功能,例如使用php流功能添加子节点$oXml->AddChild("file:///user/data.xml")或添加XML字符串子节点(如$oXml->AddChild("yes");),但是基本上我只是想解决simpleXML问题。

bArray

我扩展了ArrayObject类,以便所有数组功能都可以面向对象且一致,因此您无需记住array_walk按引用对数组进行操作,而array_filter按值对数组进行操作。因此,您可以执行$oArray->flip()->Reverse()->Walk(/*callback*/);之类的操作,然后仍然以通常希望$oArray[key]的方式访问该值。

两种方法都将自己输出为Arrays和Xml,因此您可以在它们之间无缝跳转。因此,您可以$oXml->AsArray();$oArray->AsXml();我发现执行此操作比在array2xml或xml2array方法之间不断地来回传递要容易得多。

http://code.google.com/p/blibrary/source

可以重写这两个类以创建您选择的自定义类,并且可以彼此独立使用。


嘿,@ Conrad我只是修改您的代码以与数字数组配合使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/**
 * Build A XML Data Set
 *
 * @param array $data Associative Array containing values to be parsed into an XML Data Set(s)
 * @param string $startElement Root Opening Tag, default fx_request
 * @param string $xml_version XML Version, default 1.0
 * @param string $xml_encoding XML Encoding, default UTF-8
 * @return string XML String containig values
 * @return mixed Boolean false on failure, string XML result on success
 */

public static function arrayToXML($data, $startElement = 'fx_request', $xml_version = '1.0', $xml_encoding = 'UTF-8'){
    if(!is_array($data)){
        $err = 'Invalid variable type supplied, expected array not found on line '.__LINE__." in Class:".__CLASS__." Method:".__METHOD__;
        trigger_error($err);
        if($this->_debug) echo $err;
        return false; //return false error occurred
    }
    $xml = new XmlWriter();
    $xml->openMemory();
    $xml->startDocument($xml_version, $xml_encoding);
    $xml->startElement($startElement);

    /**
     * Write XML as per Associative Array
     * @param object $xml XMLWriter Object
     * @param array $data Associative Data Array
     */

    function write(XMLWriter $xml, $data){
        foreach($data as $key => $value){
            if (is_array($value) && isset($value[0])){
                foreach($value as $itemValue){
                    //$xml->writeElement($key, $itemValue);

                    if(is_array($itemValue)){
                        $xml->startElement($key);
                        write($xml, $itemValue);
                        $xml->endElement();
                        continue;
                    }

                    if (!is_array($itemValue)){
                        $xml->writeElement($key, $itemValue."");
                    }
                }
            }else if(is_array($value)){
                $xml->startElement($key);
                write($xml, $value);
                $xml->endElement();
                continue;
            }

            if (!is_array($value)){
                $xml->writeElement($key, $value."");
            }
        }
    }
    write($xml, $data);

    $xml->endElement();//write end element
    //returns the XML results
    return $xml->outputMemory(true);
}

所以您可以将其转换为:

1
2
3
4
5
6
7
8
9
10
11
12
13
$mArray["invitations"]["user"][0]["name"] ="paco";
$mArray["invitations"]["user"][0]["amigos"][0] = 82;
$mArray["invitations"]["user"][0]["amigos"][1] = 29;
$mArray["invitations"]["user"][0]["amigos"][2] = 6;

$mArray["invitations"]["user"][1]["name"] ="jose";
$mArray["invitations"]["user"][1]["amigos"][0] = 43;
$mArray["invitations"]["user"][1]["amigos"][1]["tuyos"] = 32;
$mArray["invitations"]["user"][1]["amigos"][1]["mios"] = 79;
$mArray["invitations"]["user"][1]["amigos"][2] = 11;

$mArray["invitations"]["user"][2]["name"] ="luis";
$mArray["invitations"]["user"][2]["amigos"][0] = 65;

到这个xml中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<invitations>
<user>
    <name>paco</name>
    82</amigos>
    29</amigos>
    6</amigos>
</user>
<user>
    <name>jose</name>
    43</amigos>
   
        <tuyos>32</tuyos>
        <mios>79</mios>
    </amigos>
    11</amigos>
</user>
<user>
    <name>luis</name>
    65</amigos>
</user>

我希望我可以帮助某人


这是我编写的用于获取XML并将其转换为PHP关联数组的函数。一个警告是,id当前不处理属性或c数据。尽管它将通过将重复的XML Tag放在以该标签命名的数组中来处理相同级别的重复XML Tag。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
<?php

$xml_req1 = <<<XML
<?xml version="1.0"?>
<Vastera:CustomerValidation_RequestInfo
      xmlns:Vastera="http://ndc-ah-prd.am.mot.com:10653/MotVastera_CustomerValidation/MC000078/Docs/">
  <PartnerID>5550000100-003</PartnerID>
  <PartnerType>PTNR_INTER_CONSIGNEE</PartnerType>
  <OperatingUnit>100</OperatingUnit>
  <Status>ACTIVE</Status>
  <CustomerSeqNumber>111</CustomerSeqNumber>
  <CustomerName>Greg Co</CustomerName>
  <Address1>123 Any Ln</Address1>
  <Address2>?</Address2>
  <Address3>?</Address3>
  <Address4>?</Address4>
  <Address5>?</Address5>
  <City>Someplace</City>
  <PostalCode>603021</PostalCode>
  <State>CA</State>
  <CountryCode>US</CountryCode>
  <TaxReference>222</TaxReference>
  <PartyRelated>Y</PartyRelated>
  <BusinessUnit>GSBU</BusinessUnit>
  <Region>GSRGN</Region>
  <LocationName>DBA Mac Head Computing</LocationName>
  <LoadOnly>N</LoadOnly>
  <VSTM>333</VSTM>
  <MilitaryCustomerFlag>Y</MilitaryCustomerFlag>
  <USFederalGovernmentCustomer>Y</USFederalGovernmentCustomer>
  <Non-USGovernmentCustomer>Y</Non-USGovernmentCustomer>
  <Vastera:EPCIActivity>
    <EPCIActivityNuclearCode>NUCLEAR</EPCIActivityNuclearCode>
    <EPCIActivityNuclearValue>N</EPCIActivityNuclearValue>
    <EPCIActivityNuclearApproveDate>2011-05-16:07:19:37</EPCIActivityNuclearApproveDate>
    <EPCIActivityNuclearExpireDate>2056-12-31:12:00:00</EPCIActivityNuclearExpireDate>
    <EPCIActivityNuclearCountry>US</EPCIActivityNuclearCountry>
    <EPCIActivityChemBioCode>CHEM_BIO</EPCIActivityChemBioCode>
    <EPCIActivityChemBioValue>N</EPCIActivityChemBioValue>
    <EPCIActivityChemBioApproveDate>2011-05-16:07:19:37</EPCIActivityChemBioApproveDate>
    <EPCIActivityChemBioExpireDate>2056-12-31:12:00:00</EPCIActivityChemBioExpireDate>
    <EPCIActivityChemBioCountry>US</EPCIActivityChemBioCountry>
    <EPCIActivityMissileCode>MISSILE</EPCIActivityMissileCode>
    <EPCIActivityMissileValue>N</EPCIActivityMissileValue>
    <EPCIActivityMissileApproveDate>2011-05-16:07:19:37</EPCIActivityMissileApproveDate>
    <EPCIActivityMissileExpireDate>2056-12-31:12:00:00</EPCIActivityMissileExpireDate>
    <EPCIActivityMissileCountry>US</EPCIActivityMissileCountry>
  </Vastera:EPCIActivity>
  <SourceSystem>GSB2BSS</SourceSystem>
  <CreatedDate>2011-05-16:07:18:55</CreatedDate>
  <CreatedBy>c18530</CreatedBy>
  <LastModifiedDate>2011-05-16:07:18:55</LastModifiedDate>
  <LastModifiedBy>c18530</LastModifiedBy>
  <ContactName>Greg,"Da Man" Skluacek</ContactName>
  <ContactTitle>Head Honcho</ContactTitle>
  <ContactPhone>555-555-5555</ContactPhone>
  <ContactFax>666-666-6666</ContactFax>
  <ContactEmail>gskluzacek@gregco.com</ContactEmail>
  <ContactWeb>www.gregco.com</ContactWeb>
</Vastera:CustomerValidation_RequestInfo>
XML
;

$xml_req2 = <<<XML
<?xml version="1.0"?>
<order>
    <orderNumber>123</orderNumber>
    <customerAddress>
        <type>Ship To</type>
        <name>Bob McFly</name>
        123 Lincoln St</addr1>
        <city>Chicago</city>
        <state>IL</state>
        <zip>60001</zip>
    </customerAddress>
    <customerAddress>
        <type>Bill To</type>
        <name>McFly Products Inc.</name>
        P.O. Box 6695</addr1>
        <city>New York</city>
        <state>NY</state>
        <zip>99081-6695</zip>
    </customerAddress>
    <item>
        <line>1</line>
        <part>123001A</part>
        <qty>5</qty>
        <price>10.25</price>
    </item>
    <item>
        <line>2</line>
        <part>456002B</part>
        <qty>3</qty>
        <price>20.50</price>
    </item>
    <item>
        <line>3</line>
        <part>789003C</part>
        <qty>1</qty>
        <price>41.00</price>
    </item>
    <orderSubTotal>133.25</orderSubTotal>
    <tax>6.66</tax>
    <shipping>10.00</shipping>
    <orderTotal>149.91</orderTotal>
</order>
XML
;

$doc = new DOMDocument();
$doc->preserveWhiteSpace = false;
$doc->loadXML($xml_req1);

$arr = xml_to_arr($doc->documentElement);

print"

----

"
;

print_r($arr);

print"

----

"
;

$doc2 = new DOMDocument();
$doc2->preserveWhiteSpace = false;
$doc2->loadXML($xml_req2);

$arr2 = xml_to_arr($doc2->documentElement);

print"

----

"
;

print_r($arr2);

print"

----

"
;

exit;

function xml_to_arr($curr_node) {
    $val_array = array();
    $typ_array = array();

    foreach($curr_node->childNodes as $node) {
        if ($node->nodeType == XML_ELEMENT_NODE) {

            $val = xml_to_arr($node);

            if (array_key_exists($node->tagName, $val_array)) {

                if (!is_array($val_array[$node->tagName]) || $type_array[$node->tagName] == 'hash') {
                    $existing_val = $val_array[$node->tagName];
                    unset($val_array[$node->tagName]);
                    $val_array[$node->tagName][0] = $existing_val;
                    $type_array[$node->tagName] = 'array';
                }
                $val_array[$node->tagName][] = $val;

            } else {

                $val_array[$node->tagName] = $val;
                if (is_array($val)) {
                    $type_array[$node->tagName] = 'hash';
                }

            } // end if array key exists

        } // end if elment node
    }// end for each

    if (count($val_array) == 0) {
        return $curr_node->nodeValue;
    } else {
        return $val_array;
    }

} // end function xml to arr

?>

示例输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
----

Array
(
    [PartnerID] => 5550000100-003
    [PartnerType] => PTNR_INTER_CONSIGNEE
    [OperatingUnit] => 100
    [Status] => ACTIVE
    [CustomerSeqNumber] => 111
    [CustomerName] => Greg Co
    [Address1] => 123 Any Ln
    [Address2] => ?
    [Address3] => ?
    [Address4] => ?
    [Address5] => ?
    [City] => Somplace
    [PostalCode] => 60123
    [State] => CA
    [CountryCode] => US
    [TaxReference] => 222
    [PartyRelated] => Y
    [BusinessUnit] => GSBU
    [Region] => GSRGN
    [LocationName] => DBA Mac Head Computing
    [LoadOnly] => N
    [VSTM] => 333
    [MilitaryCustomerFlag] => Y
    [USFederalGovernmentCustomer] => Y
    [Non-USGovernmentCustomer] => Y
    [Vastera:EPCIActivity] => Array
        (
            [EPCIActivityNuclearCode] => NUCLEAR
            [EPCIActivityNuclearValue] => N
            [EPCIActivityNuclearApproveDate] => 2011-05-16:07:19:37
            [EPCIActivityNuclearExpireDate] => 2056-12-31:12:00:00
            [EPCIActivityNuclearCountry] => US
            [EPCIActivityChemBioCode] => CHEM_BIO
            [EPCIActivityChemBioValue] => N
            [EPCIActivityChemBioApproveDate] => 2011-05-16:07:19:37
            [EPCIActivityChemBioExpireDate] => 2056-12-31:12:00:00
            [EPCIActivityChemBioCountry] => US
            [EPCIActivityMissileCode] => MISSILE
            [EPCIActivityMissileValue] => N
            [EPCIActivityMissileApproveDate] => 2011-05-16:07:19:37
            [EPCIActivityMissileExpireDate] => 2056-12-31:12:00:00
            [EPCIActivityMissileCountry] => US
        )

    [SourceSystem] => GSB2BSS
    [CreatedDate] => 2011-05-16:07:18:55
    [CreatedBy] => c18530
    [LastModifiedDate] => 2011-05-16:07:18:55
    [LastModifiedBy] => c18530
    [ContactName] => Greg,"Da Man" Skluacek
    [ContactTitle] => Head Honcho
    [ContactPhone] => 555-555-5555
    [ContactFax] => 666-666-6666
    [ContactEmail] => gskluzacek@gregco.com
    [ContactWeb] => www.gregco.com
)

----

Array
(
    [orderNumber] => 123
    [customerAddress] => Array
        (
            [0] => Array
                (
                    [type] => Ship To
                    [name] => Bob McFly
                    [addr1] => 123 Lincoln St
                    [city] => Chicago
                    [state] => IL
                    [zip] => 60001
                )

            [1] => Array
                (
                    [type] => Bill To
                    [name] => McFly Products Inc.
                    [addr1] => P.O. Box 6695
                    [city] => New York
                    [state] => NY
                    [zip] => 99081-6695
                )

        )

    [item] => Array
        (
            [0] => Array
                (
                    [line] => 1
                    [part] => 123001A
                    [qty] => 5
                    [price] => 10.25
                )

            [1] => Array
                (
                    [line] => 2
                    [part] => 456002B
                    [qty] => 3
                    [price] => 20.50
                )

            [2] => Array
                (
                    [line] => 3
                    [part] => 789003C
                    [qty] => 1
                    [price] => 41.00
                )

        )

    [orderSubTotal] => 133.25
    [tax] => 6.66
    [shipping] => 10.00
    [orderTotal] => 149.91
)

--------


听起来像SimpleXML的工作。

我建议使用稍微不同的XML结构。

并想知道为什么需要从数组转换-> XML并返回。如果您可以像所说的那样修改数组结构,为什么不只生成XML?如果已经存在采用该数组配置的某些代码,只需对其进行修改以接受XML。然后,您就有1种数据格式/输入类型,并且根本不需要转换。

1
2
3
4
5
6
7
8
9
10
<items>
  <item id="1"/>
  <item id="2"/>
  <item id="3">
  <subitems>    
    <item id="3.1"/>
    <item id="3.2" isawesome="true"/>
  </subitems>
  </item>
</items>

通常尝试Zend_Config和Zend Framework。

我想这将是一个两步过程:将数组转换为Zend_Config,将Zend_Config转换为XML。


您是否看到过PEAR包XML_Serializer?

pear_php_XML_Serializer


根据这里的答案,我制作了github repo https://github.com/jmarceli/array2xml

也许不是Internet上最漂亮的仓库,但是代码似乎运行良好。

这是可能使用的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Based on: http://stackoverflow.com/questions/99350/passing-php-associative-arrays-to-and-from-xml
class ArrayToXML {
  private $version;
  private $encoding;
  /*
   * Construct ArrayToXML object with selected version and encoding
   *
   * for available values check XmlWriter docs http://www.php.net/manual/en/function.xmlwriter-start-document.php
   * @param string $xml_version XML Version, default 1.0
   * @param string $xml_encoding XML Encoding, default UTF-8
   */

  public function __construct($xmlVersion = '1.0', $xmlEncoding = 'UTF-8') {
    $this->version = $xmlVersion;
    $this->encoding = $xmlEncoding;
  }
  /**
   * Build an XML Data Set
   *
   * @param array $data Associative Array containing values to be parsed into an XML Data Set(s)
   * @param string $startElement Root Opening Tag, default data
   * @return string XML String containig values
   * @return mixed Boolean false on failure, string XML result on success
   */

  public function buildXML($data, $startElement = 'data'){
    if(!is_array($data)){
      $err = 'Invalid variable type supplied, expected array not found on line '.__LINE__." in Class:".__CLASS__." Method:".__METHOD__;
      trigger_error($err);
      //if($this->_debug) echo $err;
      return false; //return false error occurred
    }
    $xml = new XmlWriter();
    $xml->openMemory();
    $xml->startDocument($this->version, $this->encoding);
    $xml->startElement($startElement);
    $this->writeEl($xml, $data);
    $xml->endElement();//write end element
    //returns the XML results
    return $xml->outputMemory(true);
  }
  /**
   * Write keys in $data prefixed with @ as XML attributes, if $data is an array.
   * When an @ prefixed key is found, a '%' key is expected to indicate the element itself,
   * and '#' prefixed key indicates CDATA content
   *
   * @param object $xml XMLWriter Object
   * @param array $data with attributes filtered out
   */

  protected function writeAttr(XMLWriter $xml, $data) {
    if(is_array($data)) {
      $nonAttributes = array();
      foreach($data as $key => $val) {
        //handle an attribute with elements
        if($key[0] == '@') {
          $xml->writeAttribute(substr($key, 1), $val);
        } else if($key[0] == '%') {
          if(is_array($val)) $nonAttributes = $val;
          else $xml->text($val);
        } elseif($key[0] == '#') {
          if(is_array($val)) $nonAttributes = $val;
          else {
            $xml->startElement(substr($key, 1));
            $xml->writeCData($val);
            $xml->endElement();
          }
        }
        //ignore normal elements
        else $nonAttributes[$key] = $val;
      }
      return $nonAttributes;
    }
    else return $data;
  }
  /**
   * Write XML as per Associative Array
   *
   * @param object $xml XMLWriter Object
   * @param array $data Associative Data Array
   */

  protected function writeEl(XMLWriter $xml, $data) {
    foreach($data as $key => $value) {
      if(is_array($value) && !$this->isAssoc($value)) { //numeric array
        foreach($value as $itemValue){
          if(is_array($itemValue)) {
            $xml->startElement($key);
            $itemValue = $this->writeAttr($xml, $itemValue);
            $this->writeEl($xml, $itemValue);
            $xml->endElement();
          } else {
            $itemValue = $this->writeAttr($xml, $itemValue);
            $xml->writeElement($key,"$itemValue");
          }
        }
      } else if(is_array($value)) { //associative array
        $xml->startElement($key);
        $value = $this->writeAttr($xml, $value);
        $this->writeEl($xml, $value);
        $xml->endElement();
      } else { //scalar
        $value = $this->writeAttr($xml, $value);
        $xml->writeElement($key,"$value");
      }
    }
  }
  /*
   * Check if array is associative with string based keys
   * FROM: http://stackoverflow.com/questions/173400/php-arrays-a-good-way-to-check-if-an-array-is-associative-or-sequential/4254008#4254008
   *
   * @param array $array Array to check
   */

  protected function isAssoc($array) {
    return (bool)count(array_filter(array_keys($array), 'is_string'));
  }
}

之后,只需使用ArrayToXML类。例:

1
2
$xml = new ArrayToXML();
print $xml->buildXML($input);

这建立在安格尔·洛佩斯(AngelLópez)的答案上。添加了对属性的支持。如果元素具有属性,请在它们前面加上@,并以空字符串作为键引用实际元素的内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/**
 * Build an XML Data Set
 *
 * @param array $data Associative Array containing values to be parsed into an XML Data Set(s)
 * @param string $startElement Root Opening Tag, default fx_request
 * @param string $xml_version XML Version, default 1.0
 * @param string $xml_encoding XML Encoding, default UTF-8
 * @return string XML String containig values
 * @return mixed Boolean false on failure, string XML result on success
 */

function arrayToXML($data, $startElement = 'fx_request', $xml_version = '1.0', $xml_encoding = 'UTF-8'){
  if(!is_array($data)){
    $err = 'Invalid variable type supplied, expected array not found on line '.__LINE__." in Class:".__CLASS__." Method:".__METHOD__;
    trigger_error($err);
    //if($this->_debug) echo $err;
    return false; //return false error occurred
  }
  $xml = new XmlWriter();
  $xml->openMemory();
  $xml->startDocument($xml_version, $xml_encoding);
  $xml->startElement($startElement);

  /**
   * Write keys in $data prefixed with @ as XML attributes, if $data is an array. When an @ prefixed key is found, a '' key is expected to indicate the element itself.
   * @param object $xml XMLWriter Object
   * @param array $data with attributes filtered out
   */

  function writeAttr(XMLWriter $xml, $data) {
    if(is_array($data)) {
      $nonAttributes = array();
      foreach($data as $key => $val) {
        //handle an attribute with elements
        if($key[0] == '@') {
          $xml->writeAttribute(substr($key, 1), $val);
        } else if($key == '') {
          if(is_array($val)) $nonAttributes = $val;
          else $xml->text("$val");
        }

        //ignore normal elements
        else $nonAttributes[$key] = $val;
      }
      return $nonAttributes;
    }
    else return $data;
  }

  /**
   * Write XML as per Associative Array
   * @param object $xml XMLWriter Object
   * @param array $data Associative Data Array
   */

  function writeEl(XMLWriter $xml, $data) {
    foreach($data as $key => $value) {
      if(is_array($value) && isset($value[0])) { //numeric array
        foreach($value as $itemValue){
          if(is_array($itemValue)) {
            $xml->startElement($key);
            $itemValue = writeAttr($xml, $itemValue);
            writeEl($xml, $itemValue);
            $xml->endElement();
          } else {
            $itemValue = writeAttr($xml, $itemValue);
            $xml->writeElement($key,"$itemValue");
          }
        }
      } else if(is_array($value)) { //associative array
        $xml->startElement($key);
        $value = writeAttr($xml, $value);
        writeEl($xml, $value);
        $xml->endElement();
      } else { //scalar
        $value = writeAttr($xml, $value);
        $xml->writeElement($key,"$value");
      }
    }
  }
  writeEl($xml, $data);

  $xml->endElement();//write end element
  //returns the XML results
  return $xml->outputMemory(true);
}

所以您可以将其转换为:

1
2
3
4
5
6
7
8
9
10
11
12
13
$mArray["invitations"]["user"][0]["@name"] ="paco";
$mArray["invitations"]["user"][0][""]["amigos"][0] = 82;
$mArray["invitations"]["user"][0][""]["amigos"][1] = 29;
$mArray["invitations"]["user"][0][""]["amigos"][2] = 6;

$mArray["invitations"]["user"][1]["@name"] ="jose";
$mArray["invitations"]["user"][1][""]["amigos"][0] = 43;
$mArray["invitations"]["user"][1][""]["amigos"][1]["tuyos"] = 32;
$mArray["invitations"]["user"][1][""]["amigos"][1]["mios"] = 79;
$mArray["invitations"]["user"][1][""]["amigos"][2] = 11;

$mArray["invitations"]["user"][2]["@name"] ="luis";
$mArray["invitations"]["user"][2][""]["amigos"][0] = 65;

到这个xml中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<invitations>
  <user name="paco">
    82</amigos>
    29</amigos>
    6</amigos>
  </user>
  <user name="jose">
    43</amigos>
   
      <tuyos>32</tuyos>
      <mios>79</mios>
    </amigos>
    11</amigos>
  </user>
  <user name="luis">
    65</amigos>
  </user>
</invitations>

谢谢安格尔。


我同意这是PHP文档下降的一个领域,但是对我来说,我一直将SimpleXML与xml2Array函数之类的东西混合使用。在诸如print_r之类的转储功能的帮助下,从simpleXML获得的Xml并不难导航。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
 * Write XML as per Associative Array
 * @param object $xml XMLWriter Object
 * @param array $data Associative Data Array
 */

function writeXmlRecursive(XMLWriter $xml, $data){
    foreach($data as $key => $value){
        if (is_array($value) && isset($value[0])){
            $xml->startElement($key);
            foreach($value as $itemValue){

                if(is_array($itemValue)){
                    writeXmlRecursive($xml, $itemValue);
                }
                else
                {
                    $xml->writeElement($key, $itemValue."");
                }
            }
            $xml->endElement();

        }else if(is_array($value)){
            $xml->startElement($key);
            writeXmlRecursive($xml, $value);
            $xml->endElement();
            continue;
        }

        if (!is_array($value)){
            $xml->writeElement($key, $value."");
        }
    }
}

这是最终版本,可以让我从4个嵌套级别的数组中获得所需的东西

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<items>
<item>
  <id_site>59332</id_site>
  <id>33</id>
  <wyn>196429985</wyn>
  <tombid>23</tombid>
  <tombcode>196429985</tombcode>
  <religion></religion>
  <lastname>lastname</lastname>
  <firstname>name</firstname>
  <patronymicname>patronymicname</patronymicname>
  <sex>1</sex>
  <birthday>2</birthday>
  <birthmonth>4</birthmonth>
  <birthyear>1946</birthyear>
  <deathday>13</deathday>
  <deathmonth>5</deathmonth>
  <deathyear>2006</deathyear>
  <s_comments></s_comments>
  <graveyard>17446</graveyard>
  <latitude></latitude>
  <longitude></longitude>
  <images>
   <image>
    <siteId>52225</siteId>
    <fileId>62</fileId>
    [cc lang="php"]0</prefix>
    <path>path</path>
   </image>
   <image>
    <siteId>52226</siteId>
    <fileId>63</fileId>
    [cc lang="php"]0</prefix>
    <path>path</path>
   </image>
  </images>
 </item>
<items>

从xml字符串获取assoc数组的最简单方法:

1
2
3
<?
$data_array = (array) simplexml_load_string($xml_string);
?>

下面的类使用simplexml来实现相同的功能,您只需要遍历数组并调用ximplexml的addchild。

http://snipplr.com/view.php?codeview&id=3491


推荐阅读