ParseError: niet goed gevormd (ongeldige token) met behulp van cElementTree

Ik ontvangen xml-snaren van een externe bron die kan bevat unsanitized gebruikers bijgedragen inhoud.

De volgende xml-string gaf een ParseError in cElementTree:

>>> print repr(s)
'<Comment>dddddddd\x08\x08\x08\x08\x08\x08_____</Comment>'
>>> import xml.etree.cElementTree as ET
>>> ET.XML(s)

Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    ET.XML(s)
  File "<string>", line 106, in XML
ParseError: not well-formed (invalid token): line 1, column 17

Is er een manier om cElementTree niet klagen?

InformationsquelleAutor BioGeek | 2012-10-24

 

10 Replies
  1. 26

    Het lijkt te klagen over \x08 je nodig hebt om te ontsnappen dat.

    Edit:

    Of u kunt de parser negeren van de fouten met behulp van de recover

    from lxml import etree
    parser = etree.XMLParser(recover=True)
    etree.fromstring(xmlstring, parser=parser)
    • Ik wil niet om iets te veranderen over de inhoud van het XML-ik ontvangen, ik hoef alleen maar te transformeren in een cElementTree Element.
    • Check mijn bewerken…
    • ontsnappen is niet hetzelfde als het wijzigen van btw.
    • de recover het niet langer beschikbaar voor ElementTrees XMLParser, toch? Of wat ‘lxml’? Het is niet de vanille python?
  2. 22

    Ik had dezelfde fout (met ElementTree). In mijn geval was het omdat van coderingen, en ik was in staat om het op te lossen zonder gebruik te maken van een externe bibliotheek. Hoop dat dit helpt andere mensen vinden van deze vraag op basis van de titel. (verwijzing)

    import xml.etree.ElementTree as ET
    parser = ET.XMLParser(encoding="utf-8")
    tree = ET.fromstring(xmlstring, parser=parser)

    BEWERKEN: op Basis van opmerkingen, dit antwoord kunnen verouderd zijn. Maar dit werkte terug toen het werd beantwoord…

  3. 6

    Zie dit antwoord naar een andere vraag en de volgens onderdeel van de XML-specificatie.

    De backspace – U+0008 is een ongeldig teken in XML-documenten. Het moet voorgesteld worden als een ontsnapte entiteit &#8; en kan niet optreden duidelijk.

    Als u nodig hebt om het verwerken van de XML-fragment, moet u deze vervangen \x08 in s voor het voeren in een XML-parser.

  4. 2

    Een oplossing voor gottcha voor mij, met behulp van Python ‘ s ElementTree… dit is het ongeldige token fout:

    # -*- coding: utf-8 -*-
    import xml.etree.ElementTree as ET
    
    xml = u"""<?xml version='1.0' encoding='utf8'?>
    <osm generator="pycrocosm server" version="0.6"><changeset created_at="2017-09-06T19:26:50.302136+00:00" id="273" max_lat="0.0" max_lon="0.0" min_lat="0.0" min_lon="0.0" open="true" uid="345" user="john"><tag k="test" v="Съешь же ещё этих мягких французских булок да выпей чаю" /><tag k="foo" v="bar" /><discussion><comment data="2015-01-01T18:56:48Z" uid="1841" user="metaodi"><text>Did you verify those street names?</text></comment></discussion></changeset></osm>"""
    
    xmltest = ET.fromstring(xml.encode("utf-8"))

    Echter, het werkt met de toevoeging van een koppelteken in de type codering:

    <?xml version='1.0' encoding='utf-8'?>

    Meest oneven. Iemand vond deze voetnoot in de python-docs:

    De codering string opgenomen in de XML-uitvoer dient te voldoen aan de
    toepasselijke normen. Bijvoorbeeld, “UTF-8” is geldig, maar “UTF8” is
    niet.

  5. 1

    Ik heb in zitten met hetzelfde probleem. Eindelijk bedacht wat was de oorzaak van mijn zaak. Als je de gegevens van meerdere XML-bestanden die zich in dezelfde map die u parseren ook .DS_Store bestand.
    Voor het parseren toevoegen aan deze voorwaarde

    for file in files:
        if file.endswith('.xml'):
           run_your_code...

    Deze truc hielp me

  6. 1

    Dit is waarschijnlijk een codering fout. Bijvoorbeeld ik had een xml-bestand gecodeerd in UTF-8-BOM (gecontroleerd aan de hand van de Notepad++ Codering menu) en kreeg een vergelijkbaar foutbericht weergegeven.

    De oplossing (Python 3.6)

    import io
    from xml.etree import ElementTree as ET
    
    with io.open(file, 'r', encoding='utf-8-sig') as f:
        contents = f.read()
        tree = ET.fromstring(contents)

    Controleer de codering van uw xml-bestand. Als het gebruik van andere codering, het wijzigen van de ‘utf-8-sig’ dienovereenkomstig.

  7. 1

    Geen van de bovenstaande oplossingen gewerkt voor mij. Het enige dat werkte was gebruik te maken van BeautifulSoup in plaats van ElementTree als volgt:

    from bs4 import BeautifulSoup
    
    with open("data/myfile.xml") as fp:
        soup = BeautifulSoup(fp, 'xml')

    Dan kunt u zoeken op de boom als:

    soup.find_all('mytag')
    • Er is geen ‘xml parser van BeautifulSoup‘. Wanneer u de xml parameter BeautifulSoup, het maakt gebruik van lxml’s XML-parser onder de motorkap..
    • bedankt, ja ik bedoelde die nodig is voor het installeren lxml voordat u gebruik kunt maken BeautifulSoup deze manier. Tenminste in mijn geval had ik te installeren, apart…
  8. 0

    Wat mij geholpen met die fout was Juan ‘ s antwoord – https://stackoverflow.com/a/20204635/4433222
    Maar nog niet genoeg was – na het worstelen ben ik erachter gekomen dat een XML-bestand moet worden opgeslagen met UTF-8 (zonder BOM) – codering.

    De oplossing niet werken voor “normale” UTF-8.

    • En wat het argument breng je voor dat?
    • oh, het was een lange tijd geleden. weet niet eigenlijk, maar waarschijnlijk heb ik gewoon een bestand opgeslagen dat goed in notepad++
  9. 0

    Het enige dat werkte voor mij is dat ik moest add mode en codering bij het openen van het bestand zoals hieronder:

    with open(filenames[0], mode='r',encoding='utf-8') as f:
         readFile()

    Anders is niet elke keer met een ongeldige token fout als ik gewoon dit doen:

     f = open(filenames[0], 'r')
     readFile()
  10. 0

    Ik probeerde de andere oplossingen in de antwoorden hier, maar had geen geluk. Omdat ik alleen nodig voor het uitpakken van de waarde van een enkel xml-knooppunt ik gaf in en schreef mijn functie om dit te doen:

    def ParseXmlTagContents(source, tag, tagContentsRegex):
        openTagString = "<"+tag+">"
        closeTagString = "</"+tag+">"
        found = re.search(openTagString + tagContentsRegex + closeTagString, source)
        if found:   
            start = found.regs[0][0]
            end = found.regs[0][1]
            return source[start+len(openTagString):end-len(closeTagString)]
        return ""

    Voorbeeld gebruik zou worden:

    <?xml version="1.0" encoding="utf-16"?>
    <parentNode>
        <childNode>123</childNode>
    </parentNode>
    
    ParseXmlTagContents(xmlString, "childNode", "[0-9]+")

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *