Я пытаюсь получить значение атрибута ‘rdf: resource’ из элемента ‘rdf: li’ из этого XML: http://www.ecb.europa.eu/rss/fxref-usd.html
Как правильно достичь этого? Как правильно проанализировать эти элементы RDF?
Это то, что я до сих пор:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RDF</title>
</head>
<body>
<ul>
<?php
$rdf = file_get_contents('http://www.ecb.europa.eu/rss/fxref-usd.html');
$rdf = str_replace('rdf:', 'rdf_', $rdf);
$xml = simplexml_load_string($rdf);
foreach ($xml->channel->items->rdf_Seq->rdf_li as $item) {
$attributes = $item->attributes();
if(isset($attributes['rdf_resource'])) {
echo '<li><a href ='.$attributes['rdf_resource'].' target="_blank">'.$attributes['rdf_resource'].'</a> <l/i>';
}
}
?>
</ul>
</body>
</html>
Как вы можете видеть, это своего рода взлом, и я считаю, что это не правильный путь.
Любая помощь приветствуется!
Я пытаюсь получить значение атрибута ‘rdf: resource’ из элемента ‘rdf: li’ из этого XML: http://www.ecb.europa.eu/rss/fxref-usd.html
Во-первых, это не совсем законный RDF, по крайней мере, согласно парсеру Йены. После удаления местоположения схемы xsd, которое явно не разрешено для элемента rdf: RDF, я все еще получаю ошибку: Ожидается начало или конец XML-элемента (ов). Строковые данные «U2» не допускаются. Может быть, должен быть файл rdf: parseType = ‘Literal’ для встраивания смешанного содержимого XML в RDF. Возможно ошибка чередования.
Но даже если бы это был законный RDF / XML, в вашем подходе есть две проблемы, которые в итоге окажутся хрупкими. Во-первых, очень сложно надежно обрабатывать RDF / XML с помощью инструментов XML, как объясняется в этот ответ что я написал Как получить доступ к документам OWL, используя XPath в Java?. Как правило, один и тот же граф RDF может быть сериализован в виде набора различных документов RDF / XML. Для работы с rdf: li это особенно важно: граф RDF фактически не имеет ресурсов со свойствами rdf: li, хотя в документе XML есть элементы rdf: li. Посмотри на:
2.15 Элементы свойств членства в контейнере: rdf: li и rdf: _n
RDF имеет набор свойств членства в контейнере и соответствующие им
элементы свойств, которые в основном используются с экземплярами rdf: Seq,
rdf: Bag и rdf: Alt классы, которые могут быть записаны как типизированный узел
элементы. Свойства списка: rdf: _1, rdf: _2 и т. Д. И могут быть
записывается как элементы свойства или атрибуты свойства, как показано в
Пример 17. Существует элемент специального свойства rdf: li, который
эквивалентно rdf: _1, rdf: _2 по порядку, подробно описано в разделе
7.4. Сопоставление со свойствами членства контейнера всегда выполняется в том порядке, в котором элементы специального свойства rdf: li появляются в XML —
порядок документов является значительным. Эквивалент RDF / XML для примера
17, написанный в этой форме, показан в Примере 18.
Это означает, что фрагмент RDF / XML (не совсем законный, но создает общее впечатление), например:
<ex:Collection>
<rdf:li rdf:about="member1"/>
<rdf:li rdf:about="member2"/>
</ex:Collection>
также может быть написано как:
<ex:Collection>
<rdf:_2 rdf:about="member2"/>
<rdf:_1 rdf:about="member1"/>
</ex:Collection>
Это означает, что любой подход, основанный исключительно на XML, вероятно, будет хрупким, потому что он будет зависеть от некоторой структуры, которая не всегда будет представлена одинаково.
Обычно ответом является запрос с использованием языка запросов RDF, чтобы вы могли выполнять запросы на уровне RDF. Стандартный язык запросов RDF — SPARQL. К сожалению, поскольку свойств буквально бесконечно много (rdf: _1, rdf: _2,…), это также сложно сделать эффективно в SPARQL, так как в конечном итоге вам нужно сопоставить URI, которые выглядят как rdf: _xxx, а затем выяснить что следует за этим подчеркиванием.
Итак, если вы можете получить RDF / XML в легальном формате, вы можете получить что-то вроде:
<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF xmlns="http://purl.org/rss/1.0/" xmlns:cb="http://www.cbwiki.net/wiki/index.php/Specification_1.1" xmlns:dc = "http://purl.org/dc/elements/1.1/" xmlns:dcterms = "http://purl.org/dc/terms/" xmlns:rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance">
<channel rdf:about = "http://www.ecb.europa.eu/rss/usd.html">
<title>ECB | US dollar (USD) - Euro foreign exchange reference rates</title>
<link>http://www.ecb.europa.eu/home/html/rss.en.html</link>
<description>The reference rates are based on the regular daily concertation procedure between central banks within and outside the European System of Central Banks, which normally takes place at 2.15 p.m. (14:15) ECB time.</description>
<items>
<rdf:Seq>
<rdf:li rdf:resource="http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-09&rate=1.1362" />
<rdf:li rdf:resource="http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-08&rate=1.1254" />
<rdf:li rdf:resource="http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-07&rate=1.1266" />
<rdf:li rdf:resource="http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-06&rate=1.1224" />
<rdf:li rdf:resource="http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-05&rate=1.1236" />
</rdf:Seq>
</items>
</channel>
</rdf:RDF>
Теперь запомните, что эти XML-элементы rdf: li не означают, что в графе есть свойства rdf: li, а есть куча свойств rdf: _n. В сериализации Turtle (которая похожа на синтаксис SPARQL) данные следующие:
@prefix : <http://purl.org/rss/1.0/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix cb: <http://www.cbwiki.net/wiki/index.php/Specification_1.1> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .
@prefix xsi: <http://www.w3.org/2001/XMLSchema-instance> .
<http://www.ecb.europa.eu/rss/usd.html>
a :channel ;
:description "The reference rates are based on the regular daily concertation procedure between central banks within and outside the European System of Central Banks, which normally takes place at 2.15 p.m. (14:15) ECB time." ;
:items [ a rdf:Seq ;
rdf:_1 <http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-09&rate=1.1362> ;
rdf:_2 <http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-08&rate=1.1254> ;
rdf:_3 <http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-07&rate=1.1266> ;
rdf:_4 <http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-06&rate=1.1224> ;
rdf:_5 <http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-05&rate=1.1236>
] ;
:link "http://www.ecb.europa.eu/home/html/rss.en.html" ;
:title "ECB | US dollar (USD) - Euro foreign exchange reference rates" .
Что бы я сделал на этом, чтобы посмотреть на :Предметы свойства вашего канала, проверьте, что это rdf: Seq, а затем либо возьмите все его свойства, кроме rdf: type, и просто предположите, что они являются значениями rdf: _n, или фактически получите значения свойств rdf: _xxx. Это будет выглядеть так:
prefix : <http://purl.org/rss/1.0/>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
select ?item {
<http://www.ecb.europa.eu/rss/usd.html> :items ?x .
?x a rdf:Seq .
?x ?p ?item .
filter (?p != rdf:type)
}
--------------------------------------------------------------------------------------------------------------------
| item |
====================================================================================================================
| <http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-05&rate=1.1236> |
| <http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-06&rate=1.1224> |
| <http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-07&rate=1.1266> |
| <http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-08&rate=1.1254> |
| <http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-09&rate=1.1362> |
--------------------------------------------------------------------------------------------------------------------
Или последний подход (на самом деле проверка для rdf: _):
prefix : <http://purl.org/rss/1.0/>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
select ?n ?item {
<http://www.ecb.europa.eu/rss/usd.html> :items ?x .
?x a rdf:Seq .
?x ?p ?item .
# check that ?p starts with rdf:_
filter strstarts(str(?p),str(rdf:_))
# and extract the part after rdf:_ and convert
# it to an integer
bind (xsd:integer(strafter(str(?p),str(rdf:_))) as ?n)
}
------------------------------------------------------------------------------------------------------------------------
| n | item |
========================================================================================================================
| 5 | <http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-05&rate=1.1236> |
| 4 | <http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-06&rate=1.1224> |
| 3 | <http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-07&rate=1.1266> |
| 2 | <http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-08&rate=1.1254> |
| 1 | <http://www.ecb.europa.eu/stats/exchange/eurofxref/html/eurofxref-graph-usd.en.html?date=2015-10-09&rate=1.1362> |
------------------------------------------------------------------------------------------------------------------------
Теперь вам просто нужна библиотека SPARQL для PHP. Я на самом деле не пользователь PHP, поэтому я не могу рекомендовать его, но я знаю, что есть некоторые другие вопросы о переполнении стека, касающиеся PHP и SPARQL, и что немного библиотеки там.
Других решений пока нет …