2010-10-19 35 views
2

Je travaille sur un projet en utilisant lxml. Voici un exemple xmlchemin vers l'élément avec des conditions sur les attributs parent (s) en utilisant xpath, lxml, python

<PatientsTree> 
    <Patient PatientID="SKU065427">  
    <Study StudyInstanceUID="25.2.9.2.1107.5.1.4.49339.30000006050107501192100000001"> 
     <Series SeriesInstanceUID="2.16.840.1.113669.1919.1176798690"/> 
     <Series SeriesInstanceUID="2.16.840.1.113669.1919.1177084041"/> 
     <Series SeriesInstanceUID="25.2.9.2.1107.5.1.4.49339.30000006050108064034300000000"/> 
    </Study>  
    </Patient> 
    <Patient PatientID="SKU55527"> 
    <Study StudyInstanceUID="25.2.9.2.1107.5.1.4.49339.30000006120407393721800000007"> 
     <Series SeriesInstanceUID="2.16.840.1.113669.1919.1198835144"/> 
    </Study> 
    <Study StudyInstanceUID="25.2.9.2.1107.5.1.4.49339.30000007010207164403100000013"> 
     <Series SeriesInstanceUID="2.16.840.1.113669.1919.1198835358"/>  
    </Patient> 
</PatientsTree> 

que je veuille se rendre à l'élément de série avec des conditions

  1. PatientID = "SKU55527"
  2. StudyInstanceUID = "25.2.9.2.1107.5.1.4.49339.30000007010207164403100000013" ;

Mon résultat sera:

<Series SeriesInstanceUID="2.16.840.1.113669.1919.1198835358"/> 

Si je peux comprendre cette solution alors je vais passer un peu plus dans l'apprentissage xml. PS Je travaille avec python et lxml et XPath

Répondre

3
import lxml.etree as le 
with open('data.xml') as f: 
    doc=le.parse(f) 
patientID="SKU55527" 
studyInstanceUID="25.2.9.2.1107.5.1.4.49339.30000007010207164403100000013" 
xpath='''\ 
    /PatientsTree 
     /Patient[@PatientID="{p}"] 
      /Study[@StudyInstanceUID="{s}"] 
       /Series'''.format(p=patientID,s=studyInstanceUID) 
seriesInstanceUID=doc.xpath(xpath) 
for node in seriesInstanceUID: 
    print(node.attrib) 
    # {'SeriesInstanceUID': '2.16.840.1.113669.1919.1198835358'} 
+0

Magnifiquement écrit - J'adore la lisibilité améliorée de la méthode de formatage. Je ne peux jamais m'empêcher d'apprécier à quel point lxml ressemble à une bibliothèque native. – nearlymonolith

+0

S'il vous plaît, quand le schéma est bien connu, ne démarrez pas les expressions XPath avec l'opérateur '//', car ceci trasverse tout l'arbre. –

+0

@Alejandro: Merci; c'est un bon point. J'espère que cela ne vous dérange pas de prendre votre XPath bien formaté. – unutbu

2

Cette expression XPath:

/PatientsTree 
    /Patient[@PatientID='SKU55527']  
    /Study[@StudyInstanceUID = 
      '25.2.9.2.1107.5.1.4.49339.30000007010207164403100000013'] 
     /Series 

résultats dans ce nœud sélectionné:

<Series SeriesInstanceUID="2.16.840.1.113669.1919.1198835358"/> 
+0

@Alejandro: +1 pour une solution XPath pure. –

+0

merci, pour une raison quelconque, quand j'ai essayé cette syntaxe, je n'obtenais que la liste vide, je pensais qu'il y avait quelque chose de mystique à propos de lxml que je suis encore à apprendre. J'ai trouvé cette page http://msdn.microsoft.com/en-us/library/ms256086.aspx avec quelques grands exemples de xpath – user480369

+0

@ user480369: Vous êtes bienvenu. –

1

Si vous souhaitez utiliser lxml nativement au lieu de xpath: (sinon, la solution d'unutbu est parfaite)

from lxml import etree as ET 
tree = ET.parse('some_file.xml') 
patientID="SKU55527" 
studyInstanceUID="25.2.9.2.1107.5.1.4.49339.30000007010207164403100000013" 
patient_node = tree.find(patientID) 
if not patient_node is None: 
    study_node = patient_node.find(studyInstanceUID) 
    if not study_node is None: 
     for child in study_node.getchildren(): 
      print child.attrib 
      #or do whatever useful thing you want 
    else: 
     #didn't find the study 
else: 
    #didn't find the node