Jestem w środku pisania małego i brudnego modułu, aby przekonwertować dokument XML do JSON, aby różne biblioteki JavaScript mogą wyświetlać go w tabeli. Wymaga to mi nauki używania LXML i jego różnych funkcji XPath.

Mam następujący blok kodu:

    def parse(self):

        parser = etree.XMLParser(remove_comments=True, encoding="UTF-8", no_network=True, recover=True)
        root = etree.XML(self.text, parser=parser)
        self.tree = etree.XPathElementEvaluator(root)

        print(f"test: { self.tree('/*') }")

W moim teście jednostkowym wynika to:

test_parse (test_converter.TestConverter) ... test: [<Element {http://www.ivoa.net/xml/VOTable/v1.3}VOTABLE at 0x7fa2b99a8dc0>]

Jednak, gdy próbuję zapytać jak poniżej, otrzymuję pustą listę jako wynik:

print(f"test: { self.tree('/VOTABLE*') }")

Próbowałem przygotować przestrzeń nazw, aby wybrać poniżej, bez żadnych wyników:

print(f"test: { self.tree('/{http://www.ivoa.net/xml/VOTable/v1.3}VOTABLE*') }")

Czy ktoś może mi powiedzieć, co robię debiutant?

Przykładowe dane:

<VOTABLE version="1.4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://www.ivoa.net/xml/VOTable/v1.3"
  xsi:schemaLocation="http://www.ivoa.net/xml/VOTable/v1.3 http://www.ivoa.net/xml/VOTable/v1.3">
 <DESCRIPTION>
   VizieR Astronomical Server vizier.u-strasbg.fr
    Date: 2020-11-07T11:43:26 [V1.99+ (14-Oct-2013)]
   Explanations and Statistics of UCDs:         See LINK below
   In case of problem, please report to:    cds-question@unistra.fr
   In this version, NULL integer columns are written as an empty string
   &lt;TD&gt;&lt;/TD&gt;, explicitely possible from VOTable-1.3
 </DESCRIPTION>
 <RESOURCE ID="yCat_3135" name="III/135A">
  ...
 </RESOURCE>
 ...
</VOTABLE>

Aktualizacja: rozwiązanie

Gdy Drec4s wskazał, że nie rejestruję się przestrzeni nazw zapytania, udało mi się wypracować, co robię źle. Oto blokujący blok kodu:

        parser = etree.XMLParser(remove_comments=True, encoding="UTF-8", no_network=True, recover=True)
        root = etree.XML(self.text, parser=parser)
        self.tree = etree.XPathElementEvaluator(root)
        self.tree.register_namespace("n", "http://www.ivoa.net/xml/VOTable/v1.3")
        test = self.tree("/n:VOTABLE/n:DESCRIPTION/text()")
0
Jason 22 listopad 2020, 16:20

1 odpowiedź

Najlepsza odpowiedź

Możesz użyć metody xpath, ale musisz także dołączyć mapę namespace do metody:

from lxml import etree
from io import StringIO

xmldoc =  StringIO("""
<VOTABLE version="1.4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://www.ivoa.net/xml/VOTable/v1.3"
  xsi:schemaLocation="http://www.ivoa.net/xml/VOTable/v1.3 http://www.ivoa.net/xml/VOTable/v1.3">
 <DESCRIPTION>
   VizieR Astronomical Server vizier.u-strasbg.fr
    Date: 2020-11-07T11:43:26 [V1.99+ (14-Oct-2013)]
   Explanations and Statistics of UCDs:         See LINK below
   In case of problem, please report to:    cds-question@unistra.fr
   In this version, NULL integer columns are written as an empty string
   &lt;TD&gt;&lt;/TD&gt;, explicitely possible from VOTable-1.3
 </DESCRIPTION>
 <RESOURCE ID="yCat_3135" name="III/135A">
 </RESOURCE>
</VOTABLE>
""")

tree = etree.parse(xmldoc)
root = tree.getroot()
print(root.xpath('//n:DESCRIPTION', namespaces={'n': 'http://www.ivoa.net/xml/VOTable/v1.3'})[0].text)

Wynik:

   VizieR Astronomical Server vizier.u-strasbg.fr
    Date: 2020-11-07T11:43:26 [V1.99+ (14-Oct-2013)]
   Explanations and Statistics of UCDs:         See LINK below
   In case of problem, please report to:    cds-question@unistra.fr
   In this version, NULL integer columns are written as an empty string
   <TD></TD>, explicitely possible from VOTable-1.3
1
drec4s 22 listopad 2020, 14:00