如何使用PHP simplexml获取XML命名空间属性


How to get XML namespace attributes with PHP simplexml

我对这方面还很陌生,我已经学习了一些教程(包括其他操作系统问题),但我似乎无法做到这一点。

我正在使用图书馆的EAD文件(用于描述图书馆收藏的国会图书馆XML标准,http://www.loc.gov/ead/index.html),并且我在名称空间方面遇到了问题。

XML的简化示例:

<?xml version="1.0"?>
<ead xsi:schemaLocation="urn:isbn:1-931666-22-9 http://www.loc.gov/ead/ead.xsd"  xmlns:ns2="http://www.w3.org/1999/xlink" xmlns="urn:isbn:1-931666-22-9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<c02 id="ref24" level="item">
                <did>
                    <unittitle>"Lepidoptera and seas(on) of appearance"</unittitle>
                    <unitid>1</unitid>
                    <container id="cid71717" type="Box" label="Mixed materials">1</container>
                    <physdesc>
                        <extent>Pencil</extent>
                    </physdesc>
                    <unitdate>[1817]</unitdate>
                </did>
                <dao id="ref001" ns2:actuate="onRequest" ns2:show="embed" ns2:role="" ns2:href="http://diglib.amphilsoc.org/fedora/repository/graphics:92"/>
            </c02>
            <c02 id="ref25" level="item">
                <did>
                    <unittitle>Argus carryntas (Butterfly)</unittitle>
                    <unitid>2</unitid>
                    <container id="cid71715" type="Box" label="Mixed materials">1</container>
                    <physdesc>
                        <extent>Watercolor</extent>
                    </physdesc>
                    <unitdate>[1817]</unitdate>
                </did>
                <dao ns2:actuate="onRequest" ns2:show="embed" ns2:role="" ns2:href="http://diglib.amphilsoc.org/fedora/repository/graphics:87"/>
            </c02>

根据我在其他地方找到的建议,我正在尝试这个(以及这个主题的变体):

<?php 
$entries = simplexml_load_file('test.xml');        
    foreach ($entries->c02->children('http://www.w3.org/1999/xlink') as $entry) {
      echo 'link: ', $entry->children('dao', true)->href, "'n";
  }
 ?> 

当然,这是行不通的。

您必须了解名称空间和名称空间前缀之间的区别。名称空间是xmlns属性内部的值。xmlns属性定义前缀,前缀是该节点及其子节点的实际命名空间的别名。

在您的示例中有三个名称空间:

  • http://www.w3.org/1999/xlink别名为"ns2"
  • urn:isbn:1-931666-22-9没有别名
  • http://www.w3.org/2001/XMLSchema-instance别名为"xsi"

因此,以"ns2:"开头的元素和属性在xlink命名空间中,以"xsi:"开头的元件和属性在XML模式实例命名空间中。所有没有命名空间前缀的元素都在isbn特定的命名空间中。没有命名空间前缀的属性总是在NO命名空间中。

如果查询xml-dom,则需要定义自己的名称空间前缀。xml文档中的名称空间前缀可能会更改,尤其是当它们是外部资源时。

我不使用"SimpleXML",所以这里有一个DOM示例:

<?php
$xml = <<<'XML'
<?xml version="1.0"?>
<ead 
  xsi:schemaLocation="urn:isbn:1-931666-22-9 http://www.loc.gov/ead/ead.xsd"
  xmlns:ns2="http://www.w3.org/1999/xlink" 
  xmlns="urn:isbn:1-931666-22-9" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <c02 id="ref24" level="item">
    <did>
       <unittitle>"Lepidoptera and seas(on) of appearance"</unittitle>
    </did>
  </c02>
</ead>
XML;
// create dom and load the xml
$dom = new DOMDocument();
$dom->loadXml($xml);
// create an xpath object
$xpath = new DOMXpath($dom);
// register you own namespace prefix
$xpath->registerNamespace('isbn', 'urn:isbn:1-931666-22-9');
foreach ($xpath->evaluate('//isbn:unittitle', NULL, FALSE) as $node) {
  var_dump($node->textContent);
}

输出:

string(40) ""Lepidoptera and seas(on) of appearance""

Xpath功能强大,是从XML中提取数据的最方便的方法。

在您的情况下,默认名称空间很奇怪。它看起来是动态的,所以你可能需要一种方法来阅读它

$defaultNamespace = $xpath->evaluate('string(/*/namespace::*[name() = ""])');

它从文档元素中读取不带前缀的名称空间。