【问题标题】:simplexml_load_file - redundant element with empty value is converted to new SimpleXMLElement Objectsimplexml_load_file - 具有空值的冗余元素被转换为新的 SimpleXMLElement 对象
【发布时间】:2013-07-01 11:59:47
【问题描述】:

我使用 simplexml_load_file 将 XML 文件转换为对象。 当冗余元素具有空值时,我注意到了一个问题。

我认为这个例子更容易理解:

// XML-File (Just a small excerpt look at "...")
...
<Team uID="t684">
   ...
    <Player loan="" uID="p20388">
       <Name>Manuel Neuer</Name>
       <Position>Goalkeeper</Position>
       <Stat Type="first_name">Manuel</Stat>
       <Stat Type="last_name">Neuer</Stat>
       <Stat Type="middle_name"></Stat>
       <Stat Type="known_name"></Stat>
       <Stat Type="birth_date">1986-03-27</Stat>
       <Stat Type="birth_place"></Stat>
       <Stat Type="first_nationality"></Stat>
       <Stat Type="deceased"></Stat>
       <Stat Type="preferred_foot"></Stat>
       <Stat Type="weight">92</Stat>
       <Stat Type="height">193</Stat>
       <Stat Type="jersey_num">1</Stat>
       <Stat Type="real_position">Goalkeeper</Stat>
       <Stat Type="real_position_side">Unknown</Stat>
       <Stat Type="join_date">2011-07-01</Stat>
       <Stat Type="country">Germany</Stat>
    </Player>
    ...
</Team>
...

// print_r (simplexml_load_file)
...
[Player] => Array
(
    [0] => SimpleXMLElement Object
    (
            [@attributes] => Array
            (
                    [loan] =>
                    [uID] => p20388
            )
            [Name] => Manuel Neuer
            [Position] => Goalkeeper
            [Stat] => Array(
                    [0] => Manuel
                    [1] => Neuer
                    [2] => SimpleXMLElement Object
                    (
                            [@attributes] => Array
                            (
                                    [Type] => middle_name
                            )
                    )
                    [3] => SimpleXMLElement Object
                    (
                            [@attributes] => Array
                            (
                                    [Type] => known_name
                            )
                    )
                    [4] => 1986-03-27
                    [5] => SimpleXMLElement Object
                    (
                            [@attributes] => Array
                            (
                                    [Type] => birth_place
                            )
                    )
                    [6] => SimpleXMLElement Object
                    (
                            [@attributes] => Array
                            (
                                    [Type] => first_nationality
                            )
                    )
                    [7] => SimpleXMLElement Object
                    (
                            [@attributes] => Array
                            (
                                    [Type] => deceased
                            )
                    )
                    [8] => SimpleXMLElement Object
                    (
                            [@attributes] => Array
                            (
                                    [Type] => preferred_foot
                            )
                     )
                    [9] => 92
                    [10] => 193
                    [11] => 1
                    [12] => Goalkeeper
                    [13] => Unknown
                    [14] => 2011-07-01
                    [15] => Germany
               )
)

最好将“类型”名称用作数组键,这样我就不必依赖 xml 文件中的顺序。但至少一个空的xml元素值也应该是数组中的一个空值。

例如

<Stat Type="middle_name"></Stat>

应该是

[2] => 

改为

[2] => SimpleXMLElement Object
(
    [@attributes] => Array
    (
        [Type] => middle_name
    )
)

我可以通过以下方式解决这些问题:

  1. 依靠 XML 中的稳定顺序(数字索引)
  2. 证明值是否来自 SimpleXMLElement 类型以确定它是否为空。

但这对我来说似乎不是一个好的解决方案。

我是不是做错了什么或者有什么想法可以做什么?

非常感谢

【问题讨论】:

  • 即使您以为您使用print_r,呈现给您的信息也不是真实信息。它只是 informative 与 simplexml。相反,您的认知基于 SimpleXML 有很多魔力这一事实,您最好使用它提供的asXML() 方法而不是print_rvar_dump 来转储它的内容。我敢打赌,这已经使你 80% 的问题标记过时了。
  • 很好的建议,谢谢!如果我 print_r 一个单独的 Stat 它看起来像“空” - 添加一个具有特定值的 0 索引。 Stat[1] 返回值。 Stat[1]["Type"] 返回“Type”-name,Stat[1][0] 也返回值。因此,Type 的 Switch-Case 将是最好的。谢谢
  • 这是 SimpleXMLElement 中另一个神奇的东西。 $element[0] 是所谓的自引用,因此 $element[1][0] 是该列表中第二个元素的自引用。困惑?我想是的。

标签: php xml xml-parsing simplexml


【解决方案1】:

我不太清楚你到底在问什么for,但是如果你想知道 SimpleXMLElement 是否有节点值,你可以使用strlen() PHP 中的函数。

它将采用 SimpleXMLElement 的字符串上下文,即它的节点值(至少对于您在问题中拥有的那些叶节点),因此当节点为空时将返回 0,如果它包含文本则大于零.

开箱即用的 SimpleXMLElement 不支持通过属性值访问子级。 Array-Access 的工作原理是访问属性,而不是子项;见Example #5 Using attributes

但是,您可以扩展 SimpleXMLElement 以添加该功能,例如通过 Type 属性值获取子项:

class MyXMLElement extends SimpleXMLElement
{
    public function byType($value) {
        list($result) = ((array)$this->getByAttribute('Type', $value)) + array(NULL);
        return $result[0];
    }

    public function getByAttribute($attribute, $value) {
        return $this->xpath(sprintf('.//*[@%s = "%s"]', $attribute, $value));
    }
}

这个新变种可以用来代替旧变种,这样您就可以轻松访问您要查找的内容:

$team = simplexml_load_string($buffer, 'MyXMLElement');

echo "Team ",  $team['uID'], " Player(s):\n";
foreach($team->Player as $i => $player)
{
    printf(" %d. %s %s\n", $i + 1, $player->byType('first_name'), $player->byType('last_name'));
}

例如,您在问题中得到的简化示例使 &lt;Team&gt; 成为根元素输出:

Team t684 Player(s):
 1. Manuel Neuer

您会在 SimpleXML 大纲中以及以下问题中发现通过属性值访问子级:

上次我在 Stackoverflow 上扩展 SimpleXMLElement 是在 an answerDisplaying 5 latest thumbnails from public flickr api using atom_1 and php

不,实际上我上次在 Stackoverflow 上扩展 SimpleXMLElement 是 explaining exactly the same access by attribute value thing 问题 PHP/XML - how to read multible sub's

【讨论】:

  • 感谢您的精彩解释。我想将 XML 中的数据保存到我的数据库中。但现在我知道如何使用它了。您的链接示例 #5(切换)正是我现在要做的方式。
  • 如果您仍然对按属性值访问感兴趣,我也找到了这个。原来我在不知不觉中复制了我的东西 :/: PHP/XML - how to read multible sub's :)
猜你喜欢
  • 2022-01-19
  • 2022-01-07
  • 2021-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-24
  • 2021-04-05
相关资源
最近更新 更多