2016-10-19 9 views
0

Я немного новичок в этом предмете, поэтому несите меня;Обследование боевых действий Parse SPARQL GET в R

Я обращаюсь к Ordnance Survey SPARQL Endpoint за их данные RDF из R. У меня возникла проблема с анализом возвращаемого атрибута геометрии GML.

Мой запрос SPARQL (для этого, например,) возвращает геометрию Южного избирательного округа Эдинбурга с несколькими атрибутами (имя, код и URI);

require(SPARQL) 
require(XML) 

endpoint <- "http://data.ordnancesurvey.co.uk/datasets/os-linked-data/apis/sparql" 

query <- paste0( 
"PREFIX geom: <http://data.ordnancesurvey.co.uk/ontology/geometry/> 
PREFIX geog: <http://data.ordnancesurvey.co.uk/ontology/admingeo/> 
PREFIX skos: <http://www.w3.org/2004/02/skos/core#> 

SELECT ?WestminsterConstituencyName ?gssCode ?uri ?g 
WHERE 
{ 
?uri a geog:WestminsterConstituency; 
skos:prefLabel ?WestminsterConstituencyName; 
geog:gssCode ?gssCode; 
geom:extent ?geom . 
?geom geom:asGML ?g. 
} 
HAVING(?WestminsterConstituencyName=\"Edinburgh South\")") 

В R, я хочу извлечь и отобразить эти результаты в листовке. В настоящее время у меня есть два способа получения результатов из вышеприведенного запроса;

  1. Использование запроса GET через пакет httr и создание данных XML;

    packs <- c("sp","stringr","rgdal","leaflet","gsubfn","XML","SPARQL","plyr","RColorBrewer","utils","httr") 
    lapply(packs, require, character.only = TRUE) 
    
    #format the request properly to return XML 
    request <- paste0("http://data.ordnancesurvey.co.uk/datasets/os-linked-data/apis/sparql?query=",URLencode(query, reserved = TRUE),"&output=xml") 
    
    #GET request from the endpoint and parse to XML 
    data <- GET(request) 
    data.xml <- xmlParse(content(data,"text")) 
    
  2. Использование пакета SPARQL для возврата dataframe;

    # set endpoint URL and pass query to it, just keeping the results 
    qd <- SPARQL(endpoint,query)$results 
    

При использовании любого метода, геометрия возвращается (либо в качестве переменной XML или столбца dataframe) имеют все тэги GML:

"<gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>LONG LIST OF COORDINATE PAIRS</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon>"^^<http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral> 

При использовании метода № 2, я могу выполнять следующее обходное решение для создания многоугольника, но оно кажется очень уродливым;

# BNG proj4 string 
BNG <- "+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +datum=OSGB36 +units=m +no_defs" 

# extract data to attach to SpatialPolygonDataFrame later 
data <- qd[,!(colnames(qd) == "g")] 

# extract geometry part of results 
geom <- qd[,"g"] 

# use various gsub and split functions to create a dataframe of X and Y 
geom.sub <- sub(".*<gml:coordinates> *(.*?) *</gml:coordinates>.*", "\\1", geom) 
s <- strsplit(as.character(geom.sub), ' ') 
coords <- data.frame(coords=unlist(s)) 
coords[] <- lapply(coords, as.character) 
l <- strsplit(coords$coords, ",") 
df <- ldply(l) 
colnames(df) <- c("x", "y") 
df[] <- lapply(df, as.numeric) 

# create Polygon(s) 
geom.list <- Polygons(list(Polygon(df)),1) 
final <- SpatialPolygons(list(geom.list),proj4string=CRS(BNG)) 
final.df <- SpatialPolygonsDataFrame(final,data) 

Метод 1 возвращает XML-файл, подобный этому;

<?xml version="1.0"?> 
<sparql xmlns="http://www.w3.org/2005/sparql-results#"> 
    <head> 
    <variable name="WestminsterConstituencyName"/> 
    <variable name="gssCode"/> 
    <variable name="uri"/> 
    <variable name="g"/> 
    </head> 
    <results> 
    <result> 
     <binding name="WestminsterConstituencyName"> 
     <literal>Edinburgh South</literal> 
     </binding> 
     <binding name="gssCode"> 
     <literal>S14000024</literal> 
     </binding> 
     <binding name="uri"> 
     <uri>http://data.ordnancesurvey.co.uk/id/7000000000033932</uri> 
     </binding> 
     <binding name="g"> 
     <literal datatype="http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral">&lt;gml:Polygon&gt;&lt;gml:outerBoundaryIs&gt;&lt;gml:LinearRing&gt;&lt;gml:coordinates&gt;LOTS OF COORDINATE PAIRS HERE&lt;/gml:coordinates&gt;&lt;/gml:LinearRing&gt;&lt;/gml:outerBoundaryIs&gt;&lt;/gml:Polygon&gt;</literal> 
     </binding> 
    </result> 
    </results> 
</sparql> 

Но я понятия не имею, как сделать либо многоугольники (записываемые в шейпфайлы) или даже JSON из результата Xml. Я бы предпочел работать с XML, так как хотел бы получить доступ к другим ресурсам XML.

Кроме того, действительно ли работает обработка по методу 2 (stringsplitting и т. Д.)? что данные не всегда соответствуют? Будет ли потеряна информация о многочастных полигонах? (думаю, будет). Есть ли более «правильный» метод?

Спасибо за любую помощь.

+0

ОК, я изучаю немного больше, это формат SPARQL XML. Требуется конкретная работа. – Sam

+0

это возвращает пустой список; getNodeSet (data.xml, "// ns: head", c (ns = "http://www.w3.org/2005/sparql-results")). Зачем? – Sam

+0

Если 'data <- GET (test)' in ** Получение результатов 1. ** be 'data <- GET (request)'? –

ответ

1

Я не знаю, относится ли это к вашей заинтересованности в (простой ваниль?) XML, но он рисует карту. Я параметризовал имя WestminsterConstituencyName, поэтому вы могли бы превратить это в функцию.

Я ничего не знал о GML, но Я решил использовать его как есть, вместо того, чтобы разбирать координаты во что-то более общее, как в кадре данных. После некоторых исследований я был уверен, что rgdal может служить мостом между данными GML от ОС и входами, ожидаемыми буклет. Преобразование строк в SPARQL просто устранило необходимость удаления кавычек и строкового литерала, набрав в пределах R. Я подозреваю, что rgdal может иметь возможность сделать что-то непосредственно с полигоном GML из ОС, но обернуть полигон в некоторый GML, определяющий слой, и функция была яснее для меня.

Следующим шагом будет попытка использовать текстовое соединение для readOGR, поэтому вам не нужно сохранять и затем открывать файл.

Вот Shiny implementation. Я не пытаюсь улучшить производительность, например, кеширование.

require(SPARQL) 
require(XML) 
require(leaflet) 

# requires some system libraries 
# I followed this for ubuntu 
# http://www.sarasafavi.com/installing-gdalogr-on-ubuntu.html 
# might also need to do something like 
# sudo apt-get install libgdal-dev libproj-dev 
library(rgdal) 

WestminsterConstituency <- "Edinburgh South" 

endpoint <- 
    "http://data.ordnancesurvey.co.uk/datasets/os-linked-data/apis/sparql" 

query <- paste0(
    "PREFIX geom: <http://data.ordnancesurvey.co.uk/ontology/geometry/> 
    PREFIX geog: <http://data.ordnancesurvey.co.uk/ontology/admingeo/> 
    PREFIX skos: <http://www.w3.org/2004/02/skos/core#> 

    SELECT ?WestminsterConstituencyName ?gssCode ?uri (str(?g) as ?gstr) 
    WHERE 
    { 
    ?uri a geog:WestminsterConstituency; 
    skos:prefLabel ?WestminsterConstituencyName; 
    geog:gssCode ?gssCode; 
    geom:extent ?geom . 
    ?geom geom:asGML ?g. 
    } 
    HAVING(?WestminsterConstituencyName='", 
    WestminsterConstituency, 
    "')" 
) 

qd <- SPARQL(endpoint, query)$results 

xmlres <- 
    xmlTreeParse(qd$gstr, asText = TRUE, useInternalNodes = TRUE) 

template.text <- '<?xml version="1.0" encoding="utf-8" ?> 
<ogr:FeatureCollection 
xmlns:ogr="http://ogr.maptools.org/" 
xmlns:gml="http://www.opengis.net/gml"> 
<gml:featureMember> 
<WestminsterConstituency fid="0"> 
<ogr:geometryProperty> 

</ogr:geometryProperty> 
</WestminsterConstituency> 
</gml:featureMember> 
</ogr:FeatureCollection>' 

# some node adding ideas from 
# http://stackoverflow.com/questions/35201830/r-insert-node-into-xml-tree-at-specific-location 
template.xml = xmlTreeParse(template.text, 
          useInternalNodes = TRUE, 
          asText = TRUE) 
template.top = xmlRoot(template.xml) 

name.node = newXMLNode("NAME", WestminsterConstituency) 

template.node = xmlElementsByTagName(el = template.top, 
            name = "WestminsterConstituency", 
            recursive = TRUE) 

addChildren(template.node[[1]], kids = list(name.node)) 

template.node = xmlElementsByTagName(el = template.top, 
            name = "geometryProperty", 
            recursive = TRUE) 

addChildren(template.node[[1]], kids = list(xmlres)) 

saveXML(template.top, 'expanded.gml') 

if ("GML" %in% ogrDrivers()$name) { 
    WC <- 
    try(readOGR(dsn = 'expanded.gml', layer = "WestminsterConstituency")) 
    if (class(WC) != "try-error") 
    summary(WC) 
} 

# http://www.alex-singleton.com/R-Tutorial-Materials/7-converting-coordinates.pdf 
ukgrid <- "+init=epsg:27700" 
latlong <- "+init=epsg:4326" 

# http://gis.stackexchange.com/questions/123212/assign-crs-to-shapefile-in-r 
proj4string(WC) <- CRS(ukgrid) 
WC.LL <- spTransform(WC, CRS(latlong)) 

m <- leaflet() 
m <- addTiles(m) 
m <- addPolygons(data = WC.LL, map = m) 
m 
+0

большое спасибо, я явно собираюсь положить это через Shiny, но, похоже, вы избили меня! – Sam

+0

и спасибо за синтаксический анализ XML по переменной геометрии, интересно, что вы сделали его строкой в ​​запросе SPARQL. Я не думал анализировать отдельные переменные. Я собираюсь не принимать ответ, пока у меня не было теста, но он выглядит хорошо, приветствия – Sam

+0

Спасибо за комментарии. Я отредактировал ответ, чтобы добавить некоторые из моих рассуждений, включая преобразование строк в SPARQL. Сообщите нам, как все идет к вам! –

 Смежные вопросы

  • Нет связанных вопросов^_^