参考-如何在SimpleXML中处理名称空间(带有冒号的标记和属性)? [英] Reference - how do I handle namespaces (tags and attributes with colon in) in 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.com
和https://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_r
,var_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别名.请记住,此前缀可以随时更改,例如,生成器可能会分配前缀ns1
,ns2
等,并且如果代码稍有更改,则会以不同的顺序分配它们.使用此缩写,代码将变为:
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屋!