读取XML文件作为PHP中的对象并遍历内容

时间:2018-10-05 21:38:27

标签: php xml

我试图读取XML文件中的键和值,该文件首先创建为对象,然后尝试在foreach循环中进行迭代。 我的XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<response>
<lst name="responseHeader"><int name="status">0</int><int name="QTime">10</int><lst name="params"><str name="q">*:*</str><str name="facet.field">main</str><str name="facet.mincount">1</str><str name="rows">0</str><str name="facet">on</str></lst></lst><result name="response" numFound="5473" start="0"/><lst name="facet_counts"><lst name="facet_queries"/><lst name="facet_fields"><lst name="main"><int name="Victoria University Photograph Collection">1693</int>

......

我的php代码是:

foreach($input as $int){
    echo $int->response->int;
    $arr = array();

   foreach ($int as $key => $value){
        $arr[(string)$key]=(string)$value;
   }
   $arr[]=$arr;
}
print_r($arr);

echo行不显示任何内容,并且数组仅显示不具有任何值的xml内容。因此,它仅打印[lst]。我需要在标记内检索名称和值。

谢谢。

3 个答案:

答案 0 :(得分:1)

您可以使用xpath表达式来获取int元素内lst元素的名称和值。

如果要使用名称作为键将它们放在数组中,则可以使用多维数组,其中键值位于其自己的数组中,因为当xml中的名称相同时,键使用一维数组将被覆盖。

$items = $input->xpath('/response/lst/int');
$arr = [];
foreach ($items as $item) {
    if (isset($item->attributes()->name) && trim((string)$item) !== "") {
        $arr[] = [(string)$item->attributes()->name => (string)$item];
    }
}
print_r($arr);

Demo

或者获取int标记内的所有名称和值:

$items = $input->xpath('/response/lst//*');
$arr = [];
foreach ($items as $item) {
    if (isset($item->attributes()->name) && trim((string)$item) !== "") {
        $arr[] = [(string)$item->attributes()->name => (string)$item];
    }
}
print_r($arr);

Demo

答案 1 :(得分:0)

阅读SimpleXML的PHP​​手册: http://php.net/manual/en/book.simplexml.php

此外,您的XML格式不正确,您将相同的元素名称用于不同的值。元素名称应指定值。

答案 2 :(得分:0)

我已将您的XML重新格式化以提高可读性(内容未经修改)。看起来您只在问题中发布了XML的一部分,因为最后遗漏了几个</lst>结束标记,并且也错过了</response>结束标记:

$xml = '
    <?xml version="1.0" encoding="UTF-8"?>
    <response>
        <lst name="responseHeader">
            <int name="status">0</int>
            <int name="QTime">10</int>
            <lst name="params">
                <str name="q">*:*</str>
                <str name="facet.field">main</str>
                <str name="facet.mincount">1</str>
                <str name="rows">0</str>
                <str name="facet">on</str>
            </lst>
        </lst>
        <result name="response" numFound="5473" start="0"/>
        <lst name="facet_counts">
            <lst name="facet_queries"/>
            <lst name="facet_fields">
                <lst name="main">
                    <int name="Victoria University Photograph Collection">1693</int>
                </lst>' /* added by me */ . '
            </lst>' /* added by me */ . '
        </lst>' /* added by me */ . '
    </response>' /* added by me */ . '
';

$input = simplexml_load_string($xml);

在您的情况下<response>,SimpleXML将返回对根元素的引用。如您所见,在示例代码中,此<response>元素包含两个<lst>子级和一个<result>子级。这意味着$input->lst将是一个包含两个条目的数组:两个<lst>元素,按照它们在文档中出现的顺序。

您的代码正在专门寻找<int>元素作为某事物的第一个子元素,这似乎只是第一个<lst>元素的情况。第二个<lst>元素中还有一个元素,但是该元素隐藏在depper级别上,因此我现在将其略过。因此,基本上,我们需要在<int>中寻找$input->lst[0]

$arr = array();
foreach ($input->lst[0]->int as $int) {
    // get the name from the attributes
    $name = (string)$int['name'];

    // get the element's text content
    $value = (string)$int;

    $arr[$name] = $value;
}

print_r($arr);

如果您要搜索所有(顶级)<lst>,则需要一个额外的循环:

$arr = array();
foreach ($input->lst as $lst) {
    foreach ($lst->int as $int) {
        $name = (string)$int['name'];
        $value = (string)$int;

        $arr[$name] = $value;
    }
}

print_r($arr);

在您的示例代码中,这两种情况都输出以下数组(因为第二个<int>中的<lst>被埋得更深了):

Array
(
    [status] => 0
    [QTime] => 10
)

现在,如果您想遍历任何嵌套的<lst>,不管它有多深,您都可以考虑使用它来创建递归函数:

function parseLst($lst, &$arr) {
    // note the & before $arr, this is necessary to make `$arr[$name] = $value;` work.
    // Another option would be to use `global $arr;` and not pass it as an argument,
    // or if you're doing this in a class, to use `$this->arr` instead.

    foreach ($lst->int as $int) {
        $name = (string)$int['name'];
        $value = (string)$int;

        $arr[$name] = $value;
    }

    foreach ($lst->lst as $childLst) {
        parseLst($childLst, $arr);
    }
};

$arr = array();

foreach ($input->lst as $lst) {
    parseLst($lst, $arr);
}

print_r($arr);

这将产生:

Array
(
    [status] => 0
    [QTime] => 10
    [Victoria University Photograph Collection] => 1693
)