2014-05-16 1 views
0

Nokogiri로 XML에서 값을 추출하려고합니다.동일한 이름과 다른 XPath를 가진 하위 요소를 처리하는 작업을 하시겠습니까?

같은 이름이지만 xpath가 다른 하위 요소를 배열로 분리하여 저장하려고합니다. 이러한 요소는 ProdA, ProdB입니다.

현재 저는 자식 요소를 인쇄하려고하는데, 지금까지 "SDocument"만 인쇄하고 자식 요소는 인쇄하지 않은 코드가 있습니다.

<?xml version="1.0" encoding="UTF-8"?> 
<Document-St-5> 
    <SDocument> 
    <ItemList> 
     <Items_A> 
     <ItemElem> 
      <Item_Values> 
      <ProdA>2</ProdA> 
      <ProdB>8</ProdB> 
      </Item_Values> 
     </ItemElem>   
     </Items_A> 
     <Items_B> 
     <ItemElem> 
      <Item_Values> 
      <ProdA>8</ProdA> 
      <ProdB>9</ProdB> 
      </Item_Values> 
     </ItemElem> 
     </Items_B> 
    </ItemList> 
    </SDocument> 
</Document-St-5> 

누군가가 날 지점 수 : 이것은 XML이

#!/usr/bin/env ruby 
require 'nokogiri' 

doc = Nokogiri::XML(File.open("input.xml")) 

a = doc.xpath("//SDocument").each do |n| 
    n if n.text? 
end 

puts a 

:이 코드는

array = [["2","8"], ["8","9"]] 

:

목표는 다음과 같이 배열을 가지고있다 올바른 방법으로 제발?


업데이트 :

내가 실제로 원하는 것은 배열에 저장하는 것입니다

, 모든 고유 자식 SDocument 노드의 요소와 여러 발행 수있는 것들의 XPath는 그들을 분류 저장합니다. 그러나 가능한 경우 어린이 이름을 모른 채 XPath를 가져오고 고유 한 XPath 만 가져옵니다. 예를 들어

:

자식 요소 StNameStCode 그런 다음에야 지금까지 XPath를 가지고 배열 것, 하나의 선두로부터 각 하나가 :의 자녀

arr_Xpath = [ ["/Document-St-5/SDocument/StName"], ["/Document-St-5/SDocument/StCode"], ... ] 

ProdA 노드의 노드 Items_A는 다음 XPath를 가지고 :

/Document-St-5/SDocument/ItemList/Items_A/ItemElem/Item_Values/ProdA 

ProdA 개 노드 노드 Items_B의 아이들이 다음 XPath를 가지고 있습니다의 :

/Document-St-5/SDocument/ItemList/Items_B/ItemElem/Item_Values/ProdA 

다음 (ProdB 노드의 XPath를 포함) 될 자식 요소 고유의 XPath의 배열 : 첫번째 알고 내가 생각

arr_Xpath = [ "/Document-St-5/SDocument/StName", 
     "/Document-St-5/SDocument/StCode", 
     "/Document-St-5/SDocument/ItemList/Items_A/ItemElem/Item_Values/ProdA", 
     "/Document-St-5/SDocument/ItemList/Items_A/ItemElem/Item_Values/ProdB", 
     "/Document-St-5/SDocument/ItemList/Items_B/ItemElem/Item_Values/ProdA", 
        "/Document-St-5/SDocument/ItemList/Items_B/ItemElem/Item_Values/ProdB" ] 

, 고유 한 XPath의 경우 doc.xpath("..")을 사용하여 각 하위 요소의 값을 가져올 수 있으며 두 개 이상의 발생이있는 경우 을 그룹화 할 수 있습니다.그래서, 내가 좀하고 싶습니다 최종 배열은 다음과 같습니다

arr_Values = [ ["WERLJ01"], ["MEKLD"],["2","9"],["8","3"],["1"],["17"]] 

장소 :

  • arr_Values[0]StName
  • arr_Values[1]이 들어있는 배열 StCode
  • 이 들어있는 배열입니다 arr_Values[2]은 노드 Items_A의 모든 ProdA 노드의 자식 값을 포함하는 배열입니다.
  • arr_Values[3]은 노드 Items_A의 모든 ProdB 노드의 값을 포함하는 배열입니다.
  • arr_Values[4]ProdA 노드의 하위 노드 인 Items_B의 값을 모두 포함하는 배열입니다.
  • arr_Values[5]ProdB 노드의 하위 노드 인 Items_B의 값을 포함하는 배열입니다.

하는 XML의 예는 다음과 같습니다

<?xml version="1.0" encoding="UTF-8"?> 
<Document-St-5> 
    <SDocument> 
    <StName>WERLJ01</StName> 
    <StCode>MEKLD</StCode> 
    <ItemList> 
    <Items_A> 
     <ItemElem> 
     <Item_Values> 
      <ProdA>2</ProdA> 
      <ProdB>8</ProdB> 
     </Item_Values> 
     </ItemElem>   
    </Items_A> 
    <Items_A> 
     <ItemElem> 
     <Item_Values> 
      <ProdA>9</ProdA> 
      <ProdB>3</ProdB> 
     </Item_Values> 
     </ItemElem>   
    </Items_A>  
    <Items_B> 
     <ItemElem> 
     <Item_Values> 
      <ProdA>1</ProdA> 
      <ProdB>17</ProdB> 
     </Item_Values> 
     </ItemElem> 
    </Items_B> 
    </ItemList> 
    </SDocument> 
</Document-St-5> 

업데이트 2 :

안녕하세요 주석 남자, 작동! "% w"와 "% w [element1 element2]"는 무엇을 의미합니까? % w [...] 양식은 2 개 이상의 요소를 허용합니까?

Nokogiri에 초보자 인 저는 XML에 200 개 이상의 고유 한 자식 노드 (고유 Xpath)가 있기 때문에 Xpath만을 언급합니다. 그런 다음 모든 자식 노드에 대해 CSS와 동일한 기술을 사용하도록 제안합니까? XML을 처리하고 자식 노드의 이름을 모른 채 같은 이름으로 요소를 배열하고 같은 Xpath를가집니다. 네가 나에게 제안하는 방식을 알고 싶다.

다시 한번 감사

+0

사람/응답자가 접근 자로 XPath 또는 CSS를 사용하는 것과 어떤 차이가 있습니까? XPaths는 특히 당신이 보여준 것처럼 덜 유연하고 좀더 장황 할 것입니다. 노드에 대한 전체 경로를 지정하면 코드가 더 취약 해집니다. XML 구조가 변경되면 앱이 중단됩니다. 대신 랜드 마크를 사용하여 원하는 데이터를 찾을 수 있습니다. –

답변

0

여기에 한 가지 방법입니다 :

require 'nokogiri' 

doc = Nokogiri::XML(<<EOT) 
<?xml version="1.0" encoding="UTF-8"?> 
<Document-St-5> 
    <SDocument> 
    <ItemList> 
     <Items_A> 
     <ItemElem> 
      <Item_Values> 
      <ProdA>2</ProdA> 
      <ProdB>8</ProdB> 
      </Item_Values> 
     </ItemElem>   
     </Items_A> 
     <Items_B> 
     <ItemElem> 
      <Item_Values> 
      <ProdA>8</ProdA> 
      <ProdB>9</ProdB> 
      </Item_Values> 
     </ItemElem> 
     </Items_B> 
    </ItemList> 
    </SDocument> 
</Document-St-5> 
EOT 

data = doc.search('SDocument').map{ |node| 
    %w[ProdA ProdB].map{ |n| node.search(n).map(&:text) } 
} 


data # => [[["2", "8"], ["8", "9"]]] 

당신이 원하는지만 가까이보다 그것은 조금 더 깊은 중첩을 초래한다.

약간 다른 방법으로, 아마도 더 쉽게 이해가된다 :

data = doc.search('SDocument').map{ |node| 
    %w[A B].map{ |ab| 
    node.at("Items_#{ ab }").search('ProdA, ProdB').map(&:text) 
    } 
} 

이유 중첩 사용자가 지정한보다 한 레벨 더 깊다 내가 XML에서 여러 <SDocument> 태그가있을 것입니다 있으리라 믿고있어입니다 . 내가 CSS 선택기를 사용하고

data = doc.search('Items_A, Items_B').map{ |node| 
    node.search('ProdA, ProdB').map(&:text) 
} 

data # => [["2", "8"], ["8", "9"]] 

공지가 쉽게 내가 코드를 원하는 지정할 수 있도록 :이 없을 경우, 다음 코드는 요구하는지으로 배열을 반환하는 비트를 수정할 수 있습니다 Items_AItems_BProdAProdB에 대한 두 가지 다른 노드를 살펴보아야합니다.문제는 완전히 바뀌 후


업데이트 : 코드 여기

require 'nokogiri' 

doc = Nokogiri::XML(<<EOT) 
<?xml version="1.0" encoding="UTF-8"?> 
<Document-St-5> 
    <SDocument> 
    <StName>WERLJ01</StName> 
    <StCode>MEKLD</StCode> 
    <ItemList> 
    <Items_A> 
     <ItemElem> 
     <Item_Values> 
      <ProdA>2</ProdA> 
      <ProdB>8</ProdB> 
     </Item_Values> 
     </ItemElem>   
    </Items_A> 
    <Items_A> 
     <ItemElem> 
     <Item_Values> 
      <ProdA>9</ProdA> 
      <ProdB>3</ProdB> 
     </Item_Values> 
     </ItemElem>   
    </Items_A>  
    <Items_B> 
     <ItemElem> 
     <Item_Values> 
      <ProdA>1</ProdA> 
      <ProdB>17</ProdB> 
     </Item_Values> 
     </ItemElem> 
    </Items_B> 
    </ItemList> 
    </SDocument> 
</Document-St-5> 
EOT 

것 :

여기
data = %w[StName StCode].map{ |n| [doc.at(n).text] } 
%w[ProdA ProdB].each do |prod| 
    data << doc.search('Items_A').map{ |item| item.at(prod).text } 
end 
%w[ProdA ProdB].each do |prod| 
    data << [doc.at("Items_B #{prod}").text] 
end 

이 캡처 된 내용은 다음과 같습니다

다음

는 셋업입니다

data # => [["WERLJ01"], ["MEKLD"], ["2", "9"], ["8", "3"], ["1"], ["17"]] 
+0

안녕 주석 남자, 답변 및 설명 주셔서 감사합니다. 아래의 질문을 참조하십시오 "업데이트 ...", 나는 그것을 업데이트했습니다. 첫 번째 설명이 정확하지 않았기 때문에, 가능한 한 제 방향으로 나를 지적 할 수 있기를 바랍니다. 미리 감사드립니다. – Zurix

+0

* 정말 * 귀하의 질문에 정확하게 질문하는 것이 중요합니다. 나중에 다른 소스 데이터 또는 다른 요구 사항을 제공하여 변경하면 답변이 완전히 변경 될 수 있으므로 같은 질문을 검색 할 때 다른 사람들에게 혼란스러운 Q & A 페이지가 표시됩니다. 또한 원하는 답을 얻기가 더 어려워 질 것입니다. –

+0

예, 허용되는 경우 오류가 발생했습니다. 그렇지 않은 경우 새로운 질문을하는 것이 더 나은지 잘 모르겠습니다. – Zurix

관련 문제