使用simplexml_load_string在php中通过URL(SRU)加载搜索和检索将返回一个空对象

时间:2018-07-08 01:41:55

标签: php xml xml-parsing

我正在尝试使用网址https://data.norge.no/data/bibsys/bibsys-bibliotekbase-bibliografiske-data-sru上的通过URL(SRU)进行搜索和检索来从库api加载搜索结果

如果您看到那里的搜索结果链接,它看起来很像XML,但是当我尝试使用下面的代码使用xml时,它只会返回一个空对象

SimpleXMLElement {#546}

这是怎么回事?

我的laravel项目中的php函数:

public function bokId($bokid) {
    $apiUrl = "http://sru.bibsys.no/search/biblio?version=1.2&operation=searchRetrieve&startRecord=1&maximumRecords=10&query=ibsen&recordSchema=marcxchange";
    $filename = "bok.xml";
    $xmlfile = file_get_contents($apiUrl);
    file_put_contents($filename, $xmlfile); // xml file is saved.
    $fileXml = simplexml_load_string($xmlfile);
    dd($fileXml);
}

如果我这样做:

 dd($xmlfile);

相反,它像这样回显:enter image description here

让我很困惑,我无法使用任何对象。我现在提供的代码以前运行良好。

1 个答案:

答案 0 :(得分:1)

您提供的数据可能已更改格式,但是数据仍然存在,您仍然可以使用它。使用诸如dd()之类的东西的主要问题是,它不能与SimpleXMLElements一起很好地工作,它倾向于对要查看的数据有自己的想法。

在这种情况下,名称空间是常见问题。但是,如果您看下面的代码,您会发现从特定名称空间获取数据的快速方法,然后您可以像往常一样轻松地进行访问。在这段代码中,我使用->children("srw", true)来表示获取名称空间srw中的所有子元素(第二个参数表示这是前缀而不是URL)...

$apiUrl = "http://sru.bibsys.no/search/biblio?version=1.2&operation=searchRetrieve&startRecord=1&maximumRecords=10&query=ibsen&recordSchema=marcxchange";
$filename = "bok.xml";
$xmlfile = file_get_contents($apiUrl);
file_put_contents($filename, $xmlfile); // xml file is saved.
$fileXml = simplexml_load_string($xmlfile);

foreach ( $fileXml->children("srw", true)->records->record as $record)  {
    echo "recordIdentifier=".$record->recordIdentifier.PHP_EOL;
}

这将输出...

recordIdentifier=792012771
recordIdentifier=941956423
recordIdentifier=941956466
recordIdentifier=950546232
recordIdentifier=802109055
recordIdentifier=910941041
recordIdentifier=940589451
recordIdentifier=951721941
recordIdentifier=080703852
recordIdentifier=011800283

由于我不确定要检索哪些数据作为标题,因此我只想展示在有可能的情况下如何获取数据的想法。在此示例中,我使用XPath查找每个<srw:record>元素并找到<marc:datafield tag="100"...>元素以及其中的<marc:subfield code="a">元素。这是使用//marc:datafield[@tag='100']/marc:subfield[@code='a']完成的。您可能需要将@tag=的位调整为after的数据字段,并将@code=的位置调整为after的子字段。

$fileXml = simplexml_load_string($xmlfile);
$fileXml->registerXPathNamespace("marc","info:lc/xmlns/marcxchange-v1");

foreach ( $fileXml->children("srw", true)->records->record as $record)  {
    echo "recordIdentifier=".$record->recordIdentifier.PHP_EOL;

    $data = $record->xpath("//marc:datafield[@tag='100']/marc:subfield[@code='a']");
    $subData=$data[0]->children("marc", true);
    echo "Data=".(string)$data[0].PHP_EOL;
}