Я пытаюсь получить два вектора одинаковой длины, один с атрибутами дочерних элементов, а второй с атрибутами соответствующих родителей.Файл примера:
countries.xml <- "<country>
<city id='1'>
<place id='1.1'> xxx </place>
<place id='1.2'> xxx </place>
<place id='1.3'> xxx </place>
</city>
<city id='2'>
<place id='2.1'> xxx </place>
<place id='2.2'> xxx </place>
<place id='2.3'> xxx </place>
</city>
</country>"
Мой код пока
library("XML")
doc = xmlTreeParse(countries.xml, useInternalNodes = T)
xpathSApply(doc, path = "//city/place/@id")
xpathSApply(doc, path = "//city/place/parent::*/@id")
Я надеялся получить такие векторы (с именем)
"1.1" "1.2" "1.3" "2.1" "2.2" "2.3"
"1" "1" "1" "2" "2" "2"
, но вместо второгопуть производит
"1" "2"
Я могу получить то, что я хотел с циклом
library(glue)
place_id <- unname(xpathSApply(doc, path = "//city/place/@id"))
city_id <- vector()
for(i in place_id){
city_id <- c(city_id,unname(xpathSApply(doc, path = glue("//city/place[@id={i}]/parent::*/@id"))))
}
city_id
"1" "1" "1" "2" "2" "2"
, но это очень неэффективно и занимает много времени с большим xml.file, с которым я имею дело.Я уверен, что есть способ получить то, что мне нужно, с помощью правильного пути в xpathSApply
, но не смог его найти, поэтому, пожалуйста, кто-нибудь может меня осветить:)?
ОБНОВЛЕНИЕ @Решение Wietze314 прекрасно работает на моем простом примере, но я не могу адаптировать его к более сложному XML-файлу.Мне удалось изменить его код в соответствии с приведенным ниже примером
countries.xml <- "<continent>
<country id='c1'>
<city id='1'>
<place id='1.1'> xxx </place>
<place id='1.2'> xxx </place>
<place id='1.3'> xxx </place>
</city>
<city id='2'>
<place id='2.1'> xxx </place>
<place id='2.2'> xxx </place>
<place id='2.3'> xxx </place>
</city>
</country>
<country id=c2'>
<city id='1'>
<place id='1.1'> xxx </place>
<place id='1.2'> xxx </place>
<place id='1.3'> xxx </place>
</city>
<city id='2'>
<place id='2.1'> xxx </place>
<place id='2.2'> xxx </place>
<place id='2.3'> xxx </place>
</city>
</country>
</continent>"
этот код
pmap_df(list(
xml_children(cntry) %>% map(xml_children) %>%
map(xml_attr,'id') %>% unlist() %>% as.list() %>%
map(~as_tibble(.) %>% select(city = value)),
xml_children(cntry) %>% xml_children() %>% map(xml_children) %>%
map(xml_attr,'id') %>%
map(~as_tibble(.) %>% select(place = value))),cbind)
возвращает этот
city place
1 1 1.1
2 1 1.2
3 1 1.3
4 2 2.1
5 2 2.2
6 2 2.3
7 3 3.1
8 3 3.2
9 3 3.3
10 4 4.1
11 4 4.2
12 4 4.3
, но тот же код применяется к файлуиз моих интересов не удается :( любое предложение?
pfile <- http://nextbike.net/maps/nextbike-official.xml",
useInternalNodes = T)
pmap_df(list(
xml_children(pfile) %>% map(xml_children) %>%
map(xml_attr,'uid') %>% unlist() %>% as.list() %>%
map(~as_tibble(.) %>% select(city = value)),
xml_children(pfile) %>% xml_children() %>% map(xml_children) %>%
map(xml_attr,'uid') %>%
map(~as_tibble(.) %>% select(place = value))),cbind)
Error in data.frame(..., check.names = FALSE) :
arguments imply differing number of rows: 1, 0