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

时间:2013-12-02 21:05:12

标签: php xml simplexml

我对此很陌生,我已经学过几个教程(包括other OS questions),但我似乎无法让它工作。

我正在使用图书馆的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";

  }
 ?> 

当然,这不起作用。

1 个答案:

答案 0 :(得分:1)

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

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

因此,以“ns2:”开头的元素和属性位于xlink名称空间内,XML架构实例名称空间中以“xsi:”开头的元素和属性。没有名称空间前缀的所有元素都在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中提取数据的最舒适方式。

你的默认命名空间很奇怪。看起来它是动态的,所以你可能需要一种方法来阅读它。这是Xpath:

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

它从文档元素中读取没有前缀的命名空间。