2017-01-26 4 views
1

2 개의 기준과 일치하는 tag = ITEM을 찾아이 find를 기반으로 parent 태그 = NODE @ name을 가져와야합니다.ElementTree AND와 'parent'를 사용하여 노드 (XPATH)를 검색하는 더 좋은 방법

두 가지 문제 : 내가 할 '와'하는 XPath를위한 방법을 찾을 수 없습니다

  1. , 예를

    item = node.findall('./ITEM[@name="toppas_type" and @value="output file list"]') 
    
  2. 명시 적으로 검색 할 필요없이 부모 노드 정보를 얻기위한 항목을 찾기 전에 미리 저장하십시오. 예 :

    parent_name = item.parent.attrib['name'] 
    

@Mathias 뮐러 :

node_names = [] 
for node in tree.findall('NODE[@name="vertices"]/NODE'): 
    for item in node.findall('./ITEM[@name="toppas_type"]'): 
     if item.attrib['name'] == 'toppas_type' and item.attrib['value'] == 'output file list': 
      node_names.append(node.attrib['name']) 

는 ... 이런 파일 (조각 만) ...

<?xml version="1.0" encoding="ISO-8859-1"?> 
<PARAMETERS version="1.6.2" xsi:noNamespaceSchemaLocation="http://open-ms.sourceforge.net/schemas/Param_1_6_2.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <NODE name="vertices" description=""> 
     <NODE name="23" description=""> 
      <ITEM name="recycle_output" value="false" type="string" description="" required="false" advanced="false" /> 
      <ITEM name="toppas_type" value="tool" type="string" description="" required="false" advanced="false" /> 
      <ITEM name="tool_name" value="FileConverter" type="string" description="" required="false" advanced="false" /> 
      <ITEM name="tool_type" value="" type="string" description="" required="false" advanced="false" /> 
      <ITEM name="x_pos" value="-620" type="double" description="" required="false" advanced="false" /> 
      <ITEM name="y_pos" value="-1380" type="double" description="" required="false" advanced="false" /> 
     </NODE> 

     <NODE name="24" description=""> 
      <ITEM name="recycle_output" value="false" type="string" description="" required="false" advanced="false" /> 
      <ITEM name="toppas_type" value="output file list" type="string" description="" required="false" advanced="false" /> 
      <ITEM name="x_pos" value="-440" type="double" description="" required="false" advanced="false" /> 
      <ITEM name="y_pos" value="-1480" type="double" description="" required="false" advanced="false" /> 
      <ITEM name="output_folder_name" value="" type="string" description="" required="false" advanced="false" /> 
     </NODE> 

     <NODE name="33" description=""> 
      <ITEM name="recycle_output" value="false" type="string" description="" required="false" advanced="false" /> 
      <ITEM name="toppas_type" value="merger" type="string" description="" required="false" advanced="false" /> 
      <ITEM name="x_pos" value="-620" type="double" description="" required="false" advanced="false" /> 
      <ITEM name="y_pos" value="-1540" type="double" description="" required="false" advanced="false" /> 
      <ITEM name="round_based" value="false" type="string" description="" required="false" advanced="false" /> 
     </NODE> 
    <!--(snip)--> 
    </NODE> 
</PARAMETERS> 

UPDATE 구문 분석 :

이 코드는 내가 지금 가지고 있습니다

좋은 제안 - 불행히도 XML 파일을로드하려고하면 오류가 발생합니다. 나는 lxml에 익숙하지 않다. 그래서 나는 그것을 올바르게 사용하고 있는지 확신 할 수 없다.

from lxml import etree 
root = etree.DTD("/Users/mikes/Documents/Eclipseworkspace/Bioproximity/Assay-Workflows-Mikes/protein_lfq/protein_lfq-1.1.2.toppas") 
Traceback (most recent call last): 
File "<stdin>", line 1, in <module> 
File "src/lxml/dtd.pxi", line 294, in lxml.etree.DTD.__init__ (src/lxml/lxml.etree.c:187024) 
lxml.etree.DTDParseError: Content error in the external subset, line 2, column 1 

불행하게도, ElementTree는 tree.find 아마 당신이 전혀 중첩 루프가 필요하지 않습니다

+0

당신이 무엇인지를 명확하게 보여주십시오 여기 lxml 함께 할 수있는 방법입니다 여기에 포함 된 입력 문서를 정확하게 입력하면 출력이 좋을 것입니다. 감사. –

답변

1

(XPath는) 또는 tree.findall (XPath는)에서 그 XPath를 허용하지 않습니다, 하나의 XPath 식은 충분 . 나는 당신이 될 수있는 최종 결과를 원하는 정확히 잘 모르겠지만, 여기 lxml와 예입니다

>>> import lxml.etree 
>>> s = '''<NODE name="vertices" description=""> 
... 
...  <NODE name="23" description=""> 
...  <ITEM name="recycle_output" value="false" type="string" description="" required="false" advanced="false" /> 
...  <ITEM name="toppas_type" value="tool" type="string" description="" required="false" advanced="false" /> 
...  <ITEM name="tool_name" value="FileConverter" type="string" description="" required="false" advanced="false" /> 
...  <ITEM name="tool_type" value="" type="string" description="" required="false" advanced="false" /> 
...  <ITEM name="x_pos" value="-620" type="double" description="" required="false" advanced="false" /> 
...  <ITEM name="y_pos" value="-1380" type="double" description="" required="false" advanced="false" /> 
...  </NODE> 
... 
...  <NODE name="24" description=""> 
...  <ITEM name="recycle_output" value="false" type="string" description="" required="false" advanced="false" /> 
...  <ITEM name="toppas_type" value="output file list" type="string" description="" required="false" advanced="false" /> 
...  <ITEM name="x_pos" value="-440" type="double" description="" required="false" advanced="false" /> 
...  <ITEM name="y_pos" value="-1480" type="double" description="" required="false" advanced="false" /> 
...  <ITEM name="output_folder_name" value="" type="string" description="" required="false" advanced="false" /> 
...  </NODE> 
... 
...  <NODE name="33" description=""> 
...  <ITEM name="recycle_output" value="false" type="string" description="" required="false" advanced="false" /> 
...  <ITEM name="toppas_type" value="merger" type="string" description="" required="false" advanced="false" /> 
...  <ITEM name="x_pos" value="-620" type="double" description="" required="false" advanced="false" /> 
...  <ITEM name="y_pos" value="-1540" type="double" description="" required="false" advanced="false" /> 
...  <ITEM name="round_based" value="false" type="string" description="" required="false" advanced="false" /> 
...  </NODE> 
... <!--(snip)--> 
... </NODE>''' 
>>> root = lxml.etree.fromstring(s) 
>>> root.xpath('/NODE[@name="vertices"]/NODE/ITEM[@name = "toppas_type" and @value = "output file list"]') 
[<Element ITEM at 0x102b5f788>] 

그리고 당신이 실제로 부모 요소의 이름을 필요로하는 경우, 당신과 함께 부모 노드로 이동할 수 있습니다 .. :

>>> root.xpath('/NODE[@name="vertices"]/NODE/ITEM[@name = "toppas_type" and @value = "output file list"]/../@name') 
['24'] 

파일에서 XML 문서를 구문 분석

기능 etree.DTD는 XML 문서의 FR을 분석하려는 경우 잘못된 선택이다 파일 하나만. DTD는 XML 문서가 아닙니다.

>>> import lxml.etree 
>>> root = lxml.etree.parse("example.xml") 
>>> root 
<lxml.etree._ElementTree object at 0x106593b00> 

두 번째 업데이트를 가장 바깥 쪽 요소가 PARAMETERS 경우

,이 같은 검색해야합니다 :

>>> root.xpath('/PARAMETERS/NODE[@name="vertices"]/NODE/ITEM[@name = "toppas_type" and @value = "output file list"]') 
[<Element ITEM at 0x106593e18>] 
+0

좋은 제안 - 불행히도 XML 파일을로드하려고하면 오류가 발생합니다. 나는 lxml과 familliar 아니에요 ... 그래서 나는 그것이 바로 고소하고 있는지 모르겠습니다.
root = etree.DTD ("/ Users/mikes/Documents/Eclipseworkspace/Bioproximity/Assay-Workflows-Mikes/protein_lfq/protein_lfq-1.1.2.toppas ")
역 추적 (가장 최근 통화 최종) :
파일" ", 라인 1,
파일에서"SRC/LXML/dtd.pxi ", 라인 (294), lxml.etree.DTD에서 .__ init__ (src/lxml/lxml.etree.c : 187024)
lxml.etree.DTDParseError : 외부 서브셋 2 행 1 열의 내용 오류 – RightmireM

+0

@BurningKrome 질문을하면 XML 문서를 파싱하는 것처럼 보일 수 있습니다. etree.DTD'는 _DTD_로 작업하고 있음을 암시합니다 (지금까지 언급하지 않았습니다). 아마도 당신이 무엇을하려고하는지, 아니면 다른 질문을 열어야 할 필요가있을 것입니까? –

+0

죄송합니다. 이것은 XML 파일입니다. . 솔직히, 파일을 여는 방법을 검색하는 것은 DTD를 비롯한 다른 것들을 생각해 내었습니다. D – RightmireM