2017-01-06 9 views
2

私はenvelopeの束を持つXMLを持っています。それぞれの内部は配列です。配列の各行には2つの要素があります。最初のものは識別子で、2番目のものは取りたいテキストです。私は正しい値をつかむことができるように正しい行を識別するために行の最初の値が必要です。xml2:同じ行に指定したテキストの後に配列内のテキストを取得する

以下の例では、コード610954で示された行に「食品」があります。私はc('pizza', 'burger')(このコードの後に​​2つの要素をつかむしたい。同様に、コード605380で示される「ドリンク」がある。私はc('coke', 'pepsi')をつかむしたい。どのように私はこれを行うにはXML2パッケージを使用することができますか?

library(xml2) 
library(magrittr) 

myxml <- read_xml(' 
<inside> 
<envelope> 
    <card-entries type="array"> 
    <card-entry> 
     <card-id type="integer">605380</card-id> 
     <value>coke</value> 
    </card-entry> 
    <card-entry> 
     <card-id type="integer">610954</card-id> 
     <value>pizza</value> 
    </card-entry> 
    </card-entries> 
</envelope> 
<envelope> 
    <card-entries type="array"> 
    <card-entry> 
     <card-id type="integer">605380</card-id> 
     <value>pepsi</value> 
    </card-entry> 
    <card-entry> 
     <card-id type="integer">610954</card-id> 
     <value>burger</value> 
    </card-entry> 
    </card-entries> 
</envelope> 
</inside> 
' 
) 

## as far as I can parse it (but not specific enough) 
myxml %>% 
    xml_find_all('//envelope/card-entries[@type="array"]/card-entry') %>% 
    xml_text() 

food <- -CODE THAT GIVES HERE c('pizza', 'burger')- # 610954 
drinks <- -CODE THAT GIVES HERE c('coke', 'pepsi')- # 605380 

答えて

3

myxml %>% 
    xml_find_all('//envelope/card-entries[@type="array"]/card-entry[card-id = "605380"]/value') %>% 
    xml_text() 
#[1] "coke" "pepsi" 

しかし、あなたは他のアプローチ

# get following sibling called value 
myxml %>% 
    # foods 
    xml_find_all('//card-id[text()="610954"]/following-sibling::value') %>% 
    xml_text() 
#[1] "pizza" "burger" 

# get following::value[1] - Specify [1] or you would get all following values, 
# including "pepsi". With value[1] you get only the following value. 
myxml %>% 
    # foods 
    xml_find_all('//card-id[text()="610954"]/following::value[1]') %>% 
    xml_text() 
#[1] "pizza" "burger" 

# look for value nodes with a preceding sibling with the appropriate card-id 
myxml %>% 
    # drinks 
    xml_find_all('//value[preceding-sibling::card-id[text()="605380"]]') %>% 
    xml_text() 
#[1] "coke" "pepsi" 

# Get value node that is a child of card-entry nodes with the appropriate card-id. 
# specifically looking in envelope elements 
myxml %>% 
    # drinks 
    xml_find_all('//envelope/card-entries/card-entry[card-id = "605380"]/value') %>% 
    xml_text() 
#[1] "coke" "pepsi" 

# less specific 
myxml %>% 
    xml_find_all('//card-entry[card-id = "605380"]/value') %>% 
    xml_text() 
#[1] "coke" "pepsi" 
012の様々な行くことができる:

あなたの独創的なアプローチでは、ドリンクを取得するには、次のように変更することができ

+0

ありがとうございました。すべての選択肢が私に全体的な理解を深めてくれます。 –

2

どのようなものについて:

library(tidyverse) 
library(stringr) 
myxml %>% 
    xml_find_all('//envelope/card-entries[@type="array"]/card-entry') %>% 
    xml_text() %>% 
    map(.f = str_sub, start = c(1, 7), end = c(6, 1000000L)) %>% 
    reduce(rbind) %>% 
    as_tibble() %>% 
    mutate(type = ifelse(V1 == 605380, yes = "drinks", no = "food")) 

そして、あなたは簡単に別途ドリンクや食べ物をサブセットすることができます。

関連する問題