【问题标题】:In SimpleXML, can I access a field based on an attribute directly?在 SimpleXML 中,我可以直接访问基于属性的字段吗?
【发布时间】:2014-05-23 00:15:45
【问题描述】:

我正在使用 SimpleXML 浏览一个 kml 文档,并且我正在处理一个需要按特定顺序检索属性的项目。

如果我有这样的事情:

<Placemark>
<Style><LineStyle><color>ff0000ff</color></LineStyle><PolyStyle><fill>0</fill></PolyStyle></Style>
<ExtendedData><SchemaData schemaUrl="#mizipirs">
    <SimpleData name="ZCTA5CE10">55555</SimpleData>
    <SimpleData name="GEOID10">55555</SimpleData>
    <SimpleData name="CLASSFP10">XX</SimpleData>
    <SimpleData name="MTFCC10">XXXXX</SimpleData>
    <SimpleData name="FUNCSTAT10">X</SimpleData>
    <SimpleData name="ZIPNUMERIC">XXXXX</SimpleData>
    <SimpleData name="ALAND10">XXXX</SimpleData>
    <SimpleData name="AWATER10">XXXX</SimpleData>
    <SimpleData name="INTPTLAT10">XX.XXXX</SimpleData>
    <SimpleData name="INTPTLON10">XX.XXXX</SimpleData>
    <SimpleData name="ZIPcode">XXXXX</SimpleData>
    <SimpleData name="AreaName">XXXXX</SimpleData>
    <SimpleData name="TaxYear">XXXXX</SimpleData>
    <SimpleData name="numreturns">XXX</SimpleData>
    <SimpleData name="numjointre">XXX</SimpleData>
    <SimpleData name="avg_agi">XXX</SimpleData>
</SchemaData></ExtendedData>
  <Polygon><outerBoundaryIs><LinearRing><coordinates>[lots of lat/lng data here removed for everyone's own convenience]</coordinates></LinearRing></outerBoundaryIs></Polygon>
</Placemark>

所以,如果我想访问 name = "ZIPcode" 的 SimpleData 值 - 有没有办法可以做到这一点?我在这个文档中有很多 &lt;Placemark&gt;,所以我不能使用 xpath,尽管我什至不确定如何基于属性使用 Xpath。也许这是一个选择?

编辑

我喜欢这样的东西:

if(isset($xml->Document->Folder->Placemark)){
    foreach($xml->Document->Folder->Placemark as $place) {
        $zip = $place->xpath('//SchemaData/SimpleData[@name="ZIPcode"]/text()');
    }
}

所需的效果是它会提取具有“ZIPcode”属性的 SimpleData 元素的值,并且它会为每个 Placemark 元素执行此操作。但我无法让这段代码返回任何内容。

XML 中遗漏了一些结构,但我留下了必要的部分。如果我把所有东西都留在里面,这将是一个更大的文档。

【问题讨论】:

    标签: php xpath simplexml kml


    【解决方案1】:

    (代表问题作者发布).

    我找到了真正的问题。如果您的 KML 或 XML 具有默认命名空间,则必须使用 registerXPathNamespace("c","namespace here") 定义该命名空间并在您的 xpath 调用中使用它,例如 $xml-&gt;xpath('//c:element')

    我没有收到任何错误消息,只是每次都检索一个空数组。

    【讨论】:

      【解决方案2】:

      我知道有点极端,但是为什么你不 grep 或找到包含 &lt;SimpleData name="ZIPcode"&gt; 的行

      并在这一行使用子字符串或正则表达式?

      【讨论】:

      • 因为如果你有一个有效的 XML 文件,这是一个糟糕的解决方案!?如果您有挖掘机,为什么还要使用铲子?
      • @dirkk 没必要生气。我指定这是极端的,我建议作为最后的手段,因为他明确表示我不能使用 xpath。在这种情况下,它仍然很糟糕,但只是解决问题的一种解决方法。
      • 我没有生气(我将这种感觉保留在人际关系中)。明确指出他不能使用 XPath,因为 OP 认为这是不可能用 XPath 完成的任务(这是不正确的)。使用 grep 在 XML 中搜索并不是一个好主意:如果 &lt;SimpleData/&gt; 元素中有其他属性,您的解决方案就会失败。此外,由于 OP 现在希望在每个 &lt;Placemark/&gt; 中进行搜索,因此使用 grep 实际上会更加困难。
      • 由于您对 SO 还很陌生:这实际上不是一个答案,它更像是一个答案的想法。实际答案应该包含更具体的解决方案,即要执行哪些命令。
      【解决方案3】:

      我不明白您为什么认为 XPath 无法做到这一点。事实上,它是 XPath 最基本的用例之一:

      Placemark/ExtendedData/SchemaData/SimpleData[@name="ZIPcode"]/text()
      

      【讨论】:

      • 我不知道通过属性获取某些东西的确切语法。我还假设 text() 是一个内置函数来获取值?有没有办法直接访问它?诸如“$place->ExtendedData->SchemaData->SimpleData[@name="ZIPcode"]->text()”之类的东西-尝试一下,由于“=”而出现错误。
      • @JohnSly 好的,我只是假设您已经知道,因为您确实在问题中使用了正确的 @ 语法。此外,如果您在 Google 上搜索有关学习 XPath 的内容,那么它也是您学习的第一件事。是的,text() 提取元素的文本值。如果您的处理器支持string(),实际上会更好,因为它忽略了 cmets。
      • 感谢您的帮助。自从我使用 xpath 以来已经有很长时间了,所以我试图从记忆中做到这一点。我检查了基本用法,并没有在 php.net 上看到任何通过属性使用 xpath 搜索的示例(或者我可能完全错过了它们?)。我认为这是可能的,因为这似乎是一种访问数据的简单方法。
      • @JohnSly php.net/manual/en/simplexmlelement.xpath.php 有同样的简单例子,同样在 cmets 中,一些使用属性谓词。但是当然有比 PHP 手册更好的资源来寻找 XPath 建议
      • 那么让我看看我是否可以让这变得更复杂一些。 foreach($xml->Document->Folder->Placemark as $place) { $test = $place->xpath('//SchemaData/SimpleData[@name="ZIPcode"]/text()'); } 对于我的生活,我无法让它发挥作用。注释忽略换行符。我应该包括 $place 作品,它已在本地测试。
      最近更新 更多