PHP/SimpleXML - 为单个子项和多个子项生成不同的数组

Noe*_*ore 8 php xml simplexml

我正在使用SimpleXML来解析来自不同房地产经纪人的属性列表的XML提要.XML提要的相关部分看起来像这样:

<branch name="Trustee Realtors">
    <properties>
        <property>
            <reference>1</reference>
            <price>275000</price>
            <bedrooms>3</bedrooms>
        </property>
        <property>
            <reference>2</reference>
            <price>350000</price>
            <bedrooms>4</bedrooms>
        </property>
        <property>
            <reference>3</reference>
            <price>128500</price>
            <bedrooms>4</bedrooms>
        </property>
    </properties>
</branch>
<branch name="Quick-E-Realty Inc">
    <properties>
        <property>
            <reference>4</reference>
            <price>180995</price>
            <bedrooms>3</bedrooms>
        </property>
    </properties>
</branch>
Run Code Online (Sandbox Code Playgroud)

然后转换为这样的数组:

$xml = file_get_contents($filename);
$xml = simplexml_load_string($xml);
$xml_array = json_decode(json_encode((array) $xml), 1);
$xml_array = array($xml->getName() => $xml_array);
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是,当创建数组时,单个列表的数据在数组中与多个列表的位置不同 - 我不确定如何解释这个,但如果我var_dump()它看起来像这样的多个项目的数组:

array(3) {
    [0]=>
    array(3) {
        ["reference"]=>
        string(4) "0001"
        ["price"]=>
        string(6) "275000"
        ["bedrooms"]=>
        int(3)
    }
    [1]=>
    array(3) {
        ["reference"]=>
        string(4) "0002"
        ["price"]=>
        string(6) "350000"
        ["bedrooms"]=>
        int(4)
    }
    [2]=>
    array(3) {
    ["reference"]=>
        string(4) "0003"
        ["price"]=>
        string(6) "128500"
        ["bedrooms"]=>
        int(2)
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我var_dump()单个列表的数组,它看起来像这样:

array(3) {
    ["reference"]=>
    string(4) "0004"
    ["price"]=>
    string(6) "180995"
    ["bedrooms"]=>
    int(3)
}
Run Code Online (Sandbox Code Playgroud)

但我需要它看起来像这样:

array(1) {
    [0]=>
    array(3) {
        ["reference"]=>
        string(4) "0004"
        ["price"]=>
        string(6) "180995"
        ["bedrooms"]=>
        int(3)
    }
}
Run Code Online (Sandbox Code Playgroud)

这些数组中的每一个都代表来自单个房地产经纪人的房产列表.我不确定这是否只是SimpleXML或json函数的工作方式,但我需要的是使用相同的格式(包含属性列表的数组是[0]键的值).

提前致谢!

IMS*_*SoP 6

这里要问自己的一个“跳出框框思考”的大问题是:为什么首先要将 SimpleXML 对象转换为数组?

SimpleXML 不仅仅是一个用于解析 XML 然后使用其他东西来操作它的库,它的设计正是为了您将要对该数组执行的操作。

事实上,有时具有单个元素有时具有多个元素的问题是它相对于普通数组表示的一大优势:对于您知道将是单个元素的节点,您可以省略[0]; 但对于您知道可能有多个的节点,您可以使用[0], 或foreach循环,这也可以工作

以下是 SimpleXML 与您的 XML 名副其实的一些示例:

$sxml = simplexml_load_string($xml);

// Looping over multiple nodes with the same name
// We could also use $sxml->children() to loop regardless of name
//   or even the shorthand foreach ( $sxml as $children )
foreach ( $sxml->branch as $branch ) {

    // Access an attribute using array index notation
    //   the (string) is optional here, but good habit to avoid
    //   passing around SimpleXML objects by mistake
    echo 'The branch name is: ' . (string)$branch['name'] . "\n";

    // We know there is only one <properties> node, so we can take a shortcut:
    //   $branch->properties means the same as $branch->properties[0]
    // We don't know if there are 1 or many <property> nodes, but it
    //   doesn't matter: we're asking to loop over them, so SimpleXML 
    //   knows what we mean
    foreach ( $branch->properties->property as $property ) {
        echo 'The property reference is ' . (string)$property->reference . "\n";
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上,每当我看到这个丑陋的json_decode(json_encode(把戏时,我都会有点畏缩,因为后面的代码百分之九十九比仅使用 SimpleXML 丑陋得多。

  • **为什么首先要将 SimpleXML 对象转换为数组?** - 这是我没有想到的一个非常好的观点。我遇到了与OP非常相似的问题,删除了对“数组”的转换(正如你所说,这是完全没有必要的),并得到了我所期望的。 (3认同)

Cra*_*tic 5

SimpleXML 就是这样古怪。我最近使用它试图让配置文件“更容易”编写,并在这个过程中发现 SimpleXML 并不总是表现得一致。在这种情况下,我认为您将受益于简单地检测 a 是否<property>是一组中唯一的一个,如果是,则将其单独包装在一个数组中,然后将其发送到您的循环。

注意:['root']那里是因为我需要'<root></root>'在 XML 周围包装一个元素才能使我的测试工作。

//Rebuild the properties listings
$rebuild = array();
foreach($xml_array['root']['branch'] as $key => $branch) {
    $branchName = $branch['@attributes']['name'];
    //Check to see if 'properties' is only one, if it
    //is then wrap it in an array of its own.
    if(is_array($branch['properties']['property']) && !isset($branch['properties']['property'][0])) {
        //Only one propery found, wrap it in an array
        $rebuild[$branchName] = array($branch['properties']['property']);
    } else {
        //Multiple properties found
        $rebuild[$branchName] = $branch['properties']['property'];
    }
}
Run Code Online (Sandbox Code Playgroud)

这负责重建你的财产。感觉有点hackish。但基本上您正在检测此处是否缺少多维数组:

if(is_array($branch['properties']['property']) && !isset($branch['properties']['property'][0]))
Run Code Online (Sandbox Code Playgroud)

如果您没有找到多维数组,那么您显式地创建单个<property>. 然后要测试一切是否正确重建,您可以使用以下代码:

//Now do your operation...whatever it is.
foreach($rebuild as $branch => $properties) {
    print("Listings for $branch:\n");
    foreach($properties as $property) {
        print("Reference of " . $property['reference'] . " sells at $" . $property['price'] . " for " . $property['bedrooms'] . " bedrooms.\n");
    }
    print("\n");
}
Run Code Online (Sandbox Code Playgroud)

这会产生以下输出:

Listings for Trustee Realtors:
Reference of 1 sells at $275000 for 3 bedrooms.
Reference of 2 sells at $350000 for 4 bedrooms.
Reference of 3 sells at $128500 for 4 bedrooms.

Listings for Quick-E-Realty Inc:
Reference of 4 sells at $180995 for 3 bedrooms.
Run Code Online (Sandbox Code Playgroud)

重建的转储将产生:

Array
(
    [Trustee Realtors] => Array
        (
            [0] => Array
                (
                    [reference] => 1
                    [price] => 275000
                    [bedrooms] => 3
                )

            [1] => Array
                (
                    [reference] => 2
                    [price] => 350000
                    [bedrooms] => 4
                )

            [2] => Array
                (
                    [reference] => 3
                    [price] => 128500
                    [bedrooms] => 4
                )

        )

    [Quick-E-Realty Inc] => Array
        (
            [0] => Array
                (
                    [reference] => 4
                    [price] => 180995
                    [bedrooms] => 3
                )

        )

)
Run Code Online (Sandbox Code Playgroud)

我希望这可以帮助您更接近问题的解决方案。