dro59505 2018-06-04 10:03
浏览 38

带名称空间问题的SimpleXml

I have tried almost everything but i cannot seem to read the namespaced "m:inline" element and the "feed" and "title" children from the following SimpleXMLElement dump:

SimpleXMLElement {#235
+"@attributes": array:4 [
    "rel" => "http://schemas.microsoft.com/ado/2007/08/dataservices/related/test"
    "type" => "application/atom+xml;type=feed"
    "title" => "some title"
    "href" => "JobRequisition(23453453L)/Test"
]
+"m:inline": SimpleXMLElement {#152
  +"feed": SimpleXMLElement {#123
    +"title": "jobReqLocale"

...some more data ahead skipped here

The raw xml start:

<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/jobReqLocale" type="application/atom+xml;type=feed" title="some title" href="JobRequisition(23453453L)/Test">
        <m:inline>
            <feed>
                <title type="text">jobReqLocale</title>

...

I have tried:

$simpleXmlElement = new SimpleXMLElement($xml, LIBXML_NOERROR, false);

dd($simpleXmlElement->children('m', true)->feed);

The result is always an empty SimpleXmlElement

with all kinds of variations including xpath. Am i doing something wrong? Is SimpleXML not supporting these kinds of structures?

  • 写回答

1条回答 默认 最新

  • dongshuo1257 2018-06-04 13:24
    关注

    Your document contains (at least) two namespaces: one with the local prefix m, and one with no prefix (the "default namespace"). It may actually contain other namespaces you haven't shown, or re-assign both the m: prefix and the default namespace at different points in the document, but within the fragment you've shown:

    • The inline element is in the namespace with local prefix m
    • The link, feed, and title elements are in the default namespace
    • The various attributes are in no namespace at all; peculiarly, this isn't the same as them being in the default namespace.

    As discussed on "Reference - how do I handle namespaces (tags and attributes with colon in) in SimpleXML?" the ->children() method switches namespaces, so:

    • To select the inline element, you would use ->children('m', true)->inline
    • To select the feed element inside it, you need to switch back to the default namespace, with ->children(null, true)->feed
    • To access the title element inside that, you will already be in the default namespace, so can just use ->title
    • In this particular case, it doesn't matter if you are in the default namespace or "no namespace", so the type attribute can be accessed directly with ['type']
    • Remember to cast any attribute or element to string to get its string content

    To summarise:

    $type = (string)$simpleXmlElement
        ->children('m', true)
                ->inline
        ->children(null, true)
                ->feed
                ->title
                ['type'];
    

    Note that ideally you'd hard-code the namespace URIs, which are not subject to change, rather than the prefixes. You could also avoid assuming which is the default namespace and explicitly select the null namespace when selecting attributes. That would give you something more like this:

    $type = (string)$simpleXmlElement
        ->children(XMLNS_SOMETHING)
                ->inline
        ->children(XMLNS_OTHER_THING)
                ->feed
                ->title
        ->attributes(null)
                ->type;
    
    评论

报告相同问题?

悬赏问题

  • ¥15 下图接收小电路,谁知道原理
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测
  • ¥15 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探