【问题标题】:access php simplexml with namespaces使用命名空间访问 php simplexml
【发布时间】:2013-04-15 10:57:49
【问题描述】:

-

大家好,

我正在尝试访问 XML 文件中的数据:

<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dc="http://dublincore.org/documents/dcmi-    namespace/" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/     http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd";>
 <responseDate>2013-04-15T12:14:31Z</responseDate>
 <ListRecords>
 <record>
 <header>
 <identifier>
 a1b31ab2-9efe-11df-9922-efbb156aa6c1:01442b82-59a4-627e-800f-c63de74fc109
 </identifier>
 <datestamp>2012-08-16T14:42:52Z</datestamp>
 </header>
 <metadata>
 <oai_dc:dc xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd";>
 <dc:description>...</dc:description>
 <dc:date>1921</dc:date>
 <dc:identifier>K11510</dc:identifier>
 <dc:source>Waterschap Vallei & Eem</dc:source>
 <dc:source>...</dc:source>
 <dc:source>610</dc:source>
 <dc:coverage>Bunschoten</dc:coverage>
 <dc:coverage>Veendijk</dc:coverage>
 <dc:coverage>Spakenburg</dc:coverage>
 </oai_dc:dc>
 </metadata>
 <about>...</about>
 </record>

这是 XML 的一个示例。

我需要访问 dc:date dc:source 等数据。

有人有什么想法吗?

最好的问候, 蒂姆

-- 更新--

我现在正在尝试这个:

foreach( $xml->ListRecords as $records )
{
foreach( $records AS $record )
{

    $data = $record->children( 'http://www.openarchives.org/OAI/2.0/oai_dc/' );

    $rows = $data->children( 'http://purl.org/dc/elements/1.1/' );

    echo $rows->date;


    break;
}

break;
}

【问题讨论】:

标签: php xml simplexml


【解决方案1】:

您拥有位于不同 XML 命名空间中的嵌套元素。具体来说,您还涉及两个额外的命名空间:

$nsUriOaiDc = 'http://www.openarchives.org/OAI/2.0/oai_dc/';
$nsUriDc    = 'http://purl.org/dc/elements/1.1/';

第一个用于 &lt;oai_dc:dc&gt; 元素,其中包含第二个 * &lt;dc:*&gt;* 元素,如 &lt;dc:description&gt; 等等。这些就是您要寻找的元素。

在您的代码中,您已经很好地了解了它的工作原理:

$data = $record->children( 'http://www.openarchives.org/OAI/2.0/oai_dc/' );

$rows = $data->children( 'http://purl.org/dc/elements/1.1/' );

但是有一个小错误:$data 的子代不是$record 的子代,而是$record-&gt;metadata 的子代。

您也不需要将两个 foreach 相互嵌套。代码示例:

$nsUriOaiDc = 'http://www.openarchives.org/OAI/2.0/oai_dc/';

$nsUriDc    = 'http://purl.org/dc/elements/1.1/';

$records = $xml->ListRecords->record;

foreach ($records as $record)
{    
    $data = $record->metadata->children($nsUriOaiDc);

    $rows = $data->children($nsUriDc);

    echo $rows->date;

    break;
}

/** output: 1921 **/

如果您遇到此类问题,可以使用$record-&gt;asXML('php://output'); 显示您当前正在遍历的元素。

【讨论】:

  • 就是这样!非常感谢;-)
  • 我遇到了同样的问题,非常感谢您发布此解决方案。为我节省了大量时间! :)
  • 我的问题是我已经从标题的属性中提取了命名空间 URL。但这不起作用。我从这里尝试了一个示例,但没有帮助:php.net/manual/en/simplexmlelement.attributes.php
【解决方案2】:

我认为this 是您正在寻找的。希望对您有所帮助;)

【讨论】:

  • 嘿 Julio,我试过了,但我认为因为它是命名空间中的命名空间,所以它不会那样工作。
  • @TimHanssen:不,这不会给您带来任何问题。您只需要再做一次 - 使用多个命名空间。
  • 所以我尝试使用 foreach( $xml->ListRecords as $records ) { foreach( $records AS $record ) { $data = $record->children( 'openarchives.org/OAI/2.0/oai_dc' ); $rows = $data->children('purl.org/dc/elements/1.1');回声$行->日期;休息; } 休息;我得到了错误:警告:main():节点不再存在
【解决方案3】:

使用 DomDocument 来访问 dc:date

  $STR='
<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dc="http://dublincore.org/documents/dcmi-    namespace/" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/     http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd";>
 <responseDate>2013-04-15T12:14:31Z</responseDate>
 <ListRecords>
 <record>
 <header> <identifier> a1b31ab2-9efe-11df-9922-efbb156aa6c1:01442b82-59a4-627e-800f-c63de74fc109 </identifier>
<datestamp>2012-08-16T14:42:52Z</datestamp>
</header>
<metadata>
 <oai_dc:dc xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd";>
  <dc:description>...</dc:description>
  <dc:date>1921</dc:date>
  <dc:identifier>K11510</dc:identifier>
  <dc:source>Waterschap Vallei & Eem</dc:source>
  <dc:source>...</dc:source>
  <dc:source>610</dc:source>
  <dc:coverage>Bunschoten</dc:coverage>
  <dc:coverage>Veendijk</dc:coverage>
  <dc:coverage>Spakenburg</dc:coverage>
 </oai_dc:dc>
</metadata>
<about>...</about>
</record>';

  $dom= new DOMDocument; 
  $STR= str_replace("&", "&amp;", $STR);  // disguise &s going IN to loadXML() 
  // $dom->substituteEntities = true;  // collapse &s going OUT to transformToXML() 
  $dom->recover = TRUE;
  @$dom->loadHTML('<?xml encoding="UTF-8">' .$STR); 
  // dirty fix
  foreach ($dom->childNodes as $item)
  if ($item->nodeType == XML_PI_NODE)
      $dom->removeChild($item); // remove hack
  $dom->encoding = 'UTF-8'; // insert proper

  print_r($doc->getElementsByTagName('dc')->item(0)->getElementsByTagName('date')->item(0)->textContent);

输出:

 1921

或访问dc:source

 $source= $doc->getElementsByTagName('dc')->item(0)->getElementsByTagName('source');
 foreach($source as $value){
     echo $value->textContent."\n";
 }

输出:

Waterschap Vallei & Eem
...
610

或者给你数组

 $array=array();
 $source= $doc->getElementsByTagName('dc')->item(0)->getElementsByTagName("*");
 foreach($source as $value){

     $array[$value->localName][]=$value->textContent."\n";


 } 
 print_r($array);

输出:

 Array
(
   [description] => Array
    (
        [0] => ...

    )

   [date] => Array
    (
        [0] => 1921

    )

   [identifier] => Array
    (
        [0] => K11510

    )

   [source] => Array
    (
        [0] => Waterschap Vallei & Eem

        [1] => ...

        [2] => 610

    )

   [coverage] => Array
    (
        [0] => Bunschoten

        [1] => Veendijk

        [2] => Spakenburg

    )

)

【讨论】:

    【解决方案4】:

    使用 XPath 可以更直接地处理命名空间:

    <?php
    
    // load the XML into a DOM document
    $doc = new DOMDocument;
    $doc->load('oai-response.xml'); // or use $doc->loadXML($xml) for an XML string
    
    // bind the DOM document to an XPath object
    $xpath = new DOMXPath($doc);
    
    // map all the XML namespaces to prefixes, for use in XPath queries
    $xpath->registerNamespace('oai', 'http://www.openarchives.org/OAI/2.0/');
    $xpath->registerNamespace('oai_dc', 'http://www.openarchives.org/OAI/2.0/oai_dc/');
    $xpath->registerNamespace('dc', 'http://purl.org/dc/elements/1.1/');
    
    // identify each record using an XPath query
    // collect data as either strings or arrays of strings
    foreach ($xpath->query('oai:ListRecords/oai:record/oai:metadata/oai_dc:dc') as $item) {
        $data = array(
            'date' => $xpath->evaluate('string(dc:date)', $item), // $item is the context for this query
            'source' => array(),
        );
    
        foreach ($xpath->query('dc:source', $item) as $source) {
            $data['source'][] = $source->textContent;
        }
    
        print_r($data);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-06
      • 2013-04-30
      • 1970-01-01
      • 2014-06-20
      • 2016-09-22
      相关资源
      最近更新 更多