当前位置: 首页 > 面试题库 >

参考-如何在SimpleXML中处理名称空间(带有冒号的标记和属性)?

宰父德馨
2023-03-14
问题内容

该问题旨在作为回答一个特殊问题的参考,该问题可能采用不同的形式:

  • 我有一个XML文档,其中包含多个名称空间。如何使用SimpleXML解析它?
  • 我的XML在标记名称中有一个冒号(“:”),如何使用SimpleXML访问它?
  • 当名称中带有冒号时,如何访问XML文件中的属性?

如果您的问题已作为与此问题的重复而关闭,则该问题可能与这些示例不同,但是此页面应告诉您您需要知道的内容。

这是一个说明性的示例:

$xml = '
    <?xml version="1.0" encoding="utf-8"?>
    <document xmlns="http://example.com" html" target="_blank">xmlns:ns2="https://namespaces.example.org/two" xmlns:seq="urn:example:sequences">
        <list type="short">
            <ns2:item seq:position="1">A thing</ns2:item>
            <ns2:item seq:position="2">Another thing</ns2:item>
        </list>
    </document>
';
$sx = simplexml_load_string($xml);

此代码 将不起作用 ;为什么不?

foreach ( $sx->list->ns2:item as $item ) {
    echo 'Position: ' . $item['seq:position'] . "\n";
    echo 'Item: ' . (string)$item . "\n";
}

第一个问题是->ns2:item语法无效。但将其更改为此 也不起作用

foreach ( $sx->list->{'ns2:item'} as $item ) { ... }

为什么不呢,您应该使用什么呢?


问题答案:

:标记或属性名称中的冒号()表示元素或属性在 XML名称空间中
。命名空间是一种在一个文档中组合不同XML格式/标准并跟踪哪个名称来自哪种格式的方法。冒号及其前面的部分实际上并不是标签/属性名称的一部分,它们只是指示其所在的名称空间。

XML名称空间具有 名称空间标识符 ,该 名称空间标识符
由URI(URL或URN)标识。URI并不指向任何内容,它只是某人“拥有”名称空间的一种方式。例如,SOAP标准使用名称空间,http://www.w3.org/2003/05/soap- envelope而OpenDocument文件使用(以及其他)urn:oasis:names:tc:opendocument:xmlns:meta:1.0。问题中的示例使用名称空间http://example.comhttps://namespaces.example.org/two

在文档或文档的一部分中,名称空间被赋予 本地前缀
,这是您在冒号之前看到的部分。例如,在不同的文件中,SOAP命名空间可能会被给予本地前缀soap:SOAP:SOAP- ENV:env:,或只ns1:。这些名称使用特殊xmlns属性(例如)链接回命名空间的标识符xmlns:soap="http://www.w3.org/2003/05/soap- envelope"。在特定文档中,前缀的选择完全是任意的,并且每次生成前缀时都可以更改而不会更改含义。

最后,每个文档或文档部分中都有一个 默认名称空间
,该名称空间是用于没有前缀的元素的名称空间。它由不xmlns带参数的属性定义:,例如xmlns="http://www.w3.org/2003/05/soap- envelope"。在上面的示例中,<list>位于默认名称空间中,该名称空间定义为http://example.com

有点奇怪的是, 没有前缀的属性
从不在默认名称空间中,而是在一种“空名称空间”中,标准没有明确定义。

SimpleXML给我一个空对象;怎么了?

如果在带有名称空间的SimpleXML对象上使用print_rvar_dump或类似的“转储结构”函数,则某些内容将不会显示。
它仍然在那里,可以按如下所述进行访问。

如何在SimpleXML中访问名称空间?

SimpleXML提供了两种使用命名空间的主要方法:

  • ->children()方法允许您访问特定名称空间中的子元素。它可以有效地切换您的对象以查看该名称空间,直到您再次调用它以切换回另一个名称空间。
  • ->attributes()方法以类似的方式工作,但是允许您访问特定名称空间中的 属性

这两种方法都将 名称空间标识符
作为它们的第一个参数。由于这些标识符相当长,因此定义一个常量或变量来表示您正在使用的名称空间可能很有用,因此您不必在各处复制并粘贴完整的URI。

例如,上面的示例可能变成:

define('XMLNS_EG2', 'https://namespaces.example.org/two');
define('XMLNS_SEQ', 'urn:example:sequences');
foreach ( $sx->list->children(XMLNS_EG2)->item as $item ) {
    echo 'Position: ' . $item->attributes(XMLNS_SEQ)->position . "\n";
    echo 'Item: ' . (string)$item . "\n";
}

简而言之,您还可以通过将第二个参数设置为,将方法传递给名称空间的
本地别名true。请记住,这可能前缀随时更改,例如,发电机可以分配的前缀ns1ns2等,并以不同的顺序,如果代码稍有改变它们分配。使用此缩写,代码将变为:

foreach ( $sx->list->children('ns2', true)->item as $item ) {
    echo 'Position: ' . $item->attributes('seq', true)->position . "\n";
    echo 'Item: ' . (string)$item . "\n";
}

(此缩写是在PHP 5.2中添加的,您可能会看到确实很老的示例,但使用了更冗长的版本$sx->getNamespaces来获取前缀-
标识符对的列表。这是两全其美,因为您仍然很难-编码前缀而不是标识符。)



 类似资料:
  • 我面临Elasticsearch结果的问题,该结果在属性名称中使用@。json结果片段: {“\u index”:“logs-2015.12.31”,“\u type”:“log”,“\u id”:“AVH4eA4QKV0mbJuiIHO1”,“\u score”:null,“\u source”:{“@timestamp”:“2015-12-31T14:36:35.378Z”,“beat”:{“

  • 我在使用JsonPath检查字段前面带有命名空间的json时遇到麻烦。我无法从google中找到任何东西,也无法查看现有问题或留档。我无法让任何东西正常工作。我有以下json片段: 我正在尝试检查bb:list字段,看看其中有多少项。这个JsonPath表达式似乎不起作用: “$._embedded.bb:list” 如果我删除了“bb:”,那么使用它可以使用“$._embedded.list”,

  • 问题内容: youtube.xml update_videos.php 问题答案: 所以我找到了一种使用xpath的方法,这是最好的方法还是与我的问题代码保持一致的方法?只是出于好奇。

  • 问题内容: 我正在从源头解析XML文档,并且它们使用自定义名称空间。 例如。当我使用SimpleXML进行解析时,mostix:名称空间元素均未显示或不可访问。可能是一个非常简单的解决方案,但是有什么想法吗? 问题答案: 通常,人们使用children()。

  • SimpleXML示例页的"示例#5使用属性"部分指出: 访问元素的属性,就像访问数组的元素一样。 在SimpleXMLElement中的示例#1::cHilrey()使用语法来访问子属性; 将命名空间添加到该代码,将禁用对属性的访问: 这里有很多问题指向同一个解决方案,即使用函数而不是作为数组进行访问,但没有一个答案解释原因。 使用名称空间时的这种不同行为是错误吗?文件是否过时?我们是否应该始终

  • 问题内容: 当我在下面尝试添加为属性时,我正在创建Atom供稿- 我将此作为输出- 部分被切断。我需要转义- 字符吗?还是他们以其他方式添加此命名空间? 问题答案: 如果要从名称空间/前缀向$ node 添加属性,则无需事先声明名称空间。只需使用addAttribute()的第三个参数为您在第一个参数中使用的前缀提供名称空间uri。 版画 如果不需要属性本身,则可以使用删除它,而保留名称空间声明。