参考-如何在SimpleXML中处理名称空间(带有冒号的标记和属性)? [英] Reference - how do I handle namespaces (tags and attributes with colon in) in SimpleXML?

查看:89
本文介绍了参考-如何在SimpleXML中处理名称空间(带有冒号的标记和属性)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This question is intended as a reference to answer a particularly common question, which might take different forms:

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

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

If your question has been closed as a duplicate of this, it may not be identical to these examples, but this page should tell you what you need to know.

这是一个说明性示例:

$xml = '
    <?xml version="1.0" encoding="utf-8"?>
    <document xmlns="http://example.com" 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是无效的语法;但将其更改为此无效:

The first problem is that ->ns2:item is invalid syntax; but changing it to this doesn't work either:

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

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

推荐答案

什么是XML名称空间?

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

What are XML namespaces?

A colon (:) in a tag or attribute name means that the element or attribute is in an XML namespace. Namespaces are a way of combining different XML formats / standards in one document, and keeping track of which names come from which format. The colon, and the part before it, aren't really part of the tag / attribute name, they just indicate which namespace it's in.

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.

An XML namespace has a namespace identifier, which is identified by a URI (a URL or URN). The URI doesn't point at anything, it's just a way for someone to "own" the namespace. For instance, the SOAP standard uses the namespace http://www.w3.org/2003/05/soap-envelope and an OpenDocument file uses (among others) urn:oasis:names:tc:opendocument:xmlns:meta:1.0. The example in the question uses the namespaces http://example.com and https://namespaces.example.org/two.

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

Within a document, or a section of a document, a namespace is given a local prefix, which is the part you see before the colon. For instance, in different documents, the SOAP namespace might be given the local prefix soap:, SOAP:, SOAP-ENV:, env:, or just ns1:. These names are linked back to the identifier of the namespace using a special xmlns attribute, e.g. xmlns:soap="http://www.w3.org/2003/05/soap-envelope". The choice of prefix in a particular document is completely arbitrary, and could change each time it was generated without changing the meaning.

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

Finally, there is a default namespace in each document, or section of a document, which is the namespace used for elements with no prefix. It is defined by an xmlns attribute with no :, e.g. xmlns="http://www.w3.org/2003/05/soap-envelope". In the example above, <list> is in the default namespace, which is defined as http://example.com.

有些奇怪,无前缀属性从不在默认名称空间中,而是在标准没有明确定义的无效名称空间"中.请参阅: XML命名空间和未前缀属性

Somewhat peculiarly, un-prefixed attributes are never in the default namespace, but in a kind of "void namespace", which the standard doesn't clearly define. See: XML Namespaces and Unprefixed Attributes

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

If you use print_r, var_dump, or similar "dump structure" functions on a SimpleXML object with namespaces in, some of the contents will not display. It is still there, and can be accessed as described below.

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

SimpleXML provides two main methods for using namespaces:

  • ->children()方法允许您访问特定的名称空间.它可以有效地将对象切换到该命名空间,直到再次调用它以切换回另一个命名空间为止.
  • ->attributes()方法的工作方式相似,但允许您可以在特定的命名空间中访问属性.
  • The ->children() method allows you to access child elements in a particular namespace. It effectively switches your object to look at that namespace, until you call it again to switch back, or to another namespace.
  • The ->attributes() method works in a similar way, but allows you to access attributes in a particular namespace.

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

Both of these methods take the namespace identifier as their first argument. Since these identifiers are rather long, it can be useful to define a constant or variable to represent the namespaces you're working with, so you don't have to copy and paste the full URI everywhere.

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

For instance, the example above might become:

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来将方法传递给名称空间的 local别名.请记住,此前缀可以随时更改,例如,生成器可能会分配前缀ns1ns2等,并且如果代码稍有更改,则会以不同的顺序分配它们.使用此缩写,代码将变为:

As a short-hand, you can also pass the methods the local alias of the namespace, by giving the second parameter as true. Remember that this prefix could change at any time, for instance, a generator might assign prefixes ns1, ns2, etc, and assign them in a different order if the code changes slightly. Using this short-hand, the code would become:

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来获取前缀标识符对的列表.这是两全其美的做法,因为您仍在对前缀而不是标识符进行硬编码.)

(This short-hand was added in PHP 5.2, and you may see really old examples using a more long-winded version using $sx->getNamespaces to get a list of prefix-identifier pairs. This is the worst of both worlds, as you're still hard-coding the prefix rather than the identifier.)

这篇关于参考-如何在SimpleXML中处理名称空间(带有冒号的标记和属性)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆