web-dev-qa-db-ja.com

ParseError:cElementTreeを使用した整形式ではない(無効なトークン)

サニタイズされていないユーザー投稿コンテンツを含むことができる外部ソースからxml文字列を受け取ります。

次のxml文字列は、cElementTreeでParseErrorを返しました。

>>> 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

CElementTreeが文句を言わないようにする方法はありますか?

19
BioGeek

\x08エスケープする必要があります。

編集:

または、recoverを使用してパーサーにエラーを無視させることができます

from lxml import etree
parser = etree.XMLParser(recover=True)
etree.fromstring(xmlstring, parser=parser)
26
iabdalkader

同じエラーが発生していました(ElementTreeを使用)。私の場合、これはエンコーディングが原因であり、外部ライブラリを使用せずに解決できました。これが、タイトルに基づいて他の人がこの質問を見つけるのに役立つことを願っています。 ( 参照

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

[〜#〜] edit [〜#〜]:コメントに基づいて、この答えは時代遅れかもしれません。しかし、これは答えられたときに元に戻りました...

22
juan

この回答 別の質問および 対応する部分 を参照してください。

バックスペース + 0008 は、XMLドキュメントでは無効な文字です。エスケープされたエンティティ&#8;および明白に発生することはできません。

このXMLスニペットを処理する必要がある場合は、\x08sでXMLパーサーに渡す前に。

6
Boldewyn

上記の修正はどれもうまくいきませんでした。動作したのは、次のようにBeautifulSoupの代わりにElementTreeを使用することだけでした。

from bs4 import BeautifulSoup

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

次に、ツリーを次のように検索できます。

soup.find_all('mytag')
1
tsando

私は同様の問題に悩まされています。最後に、私の特定のケースで根本的な原因が何であるかを見つけました。同じフォルダにある複数のXMLファイルからデータを読み取る場合、.DS_Storeファイルも解析します。解析する前にこの条件を追加してください

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

このトリックは私にも役立ちました

1
Yura Vasiliuk

PythonのElementTreeを使用した、私にとっての落とし穴の解決策...これには無効なトークンエラーがあります。

# -*- 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"))

ただし、エンコードタイプにハイフンを追加すると機能します。

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

最も奇妙な。 誰か この脚注は python docs で見つかりました:

XML出力に含まれるエンコード文字列は、適切な標準に準拠する必要があります。たとえば、「UTF-8」は有効ですが、「UTF8」は無効です。

1
TimSC

私のために働いた唯一のことは、以下のようにファイルを開くときにモードとエンコーディングを追加する必要があったことです:

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

そうしないと、単にこれを行うと、無効なトークンエラーで毎回失敗しました:

 f = open(filenames[0], 'r')
 readFile()
0
Vishal Kaushik

私はここの答えで他の解決策を試しましたが、運がありませんでした。単一のxmlノードから値を抽出するだけでよいので、指定して関数を作成しました。

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 ""

使用例は次のとおりです。

<?xml version="1.0" encoding="utf-16"?>
<parentNode>
    <childNode>123</childNode>
</parentNode>

ParseXmlTagContents(xmlString, "childNode", "[0-9]+")
0
the_doc

これはおそらくエンコードエラーです。たとえば、UTF-8-BOMでエンコードされたxmlファイル(Notepad ++ Encodingメニューで確認)があり、同様のエラーメッセージが表示されました。

回避策(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)

Xmlファイルのエンコードを確認してください。異なるエンコーディングを使用している場合は、それに応じて「utf-8-sig」を変更します。

0
np8

そのエラーで私を助けたのはJuanの答えでした- https://stackoverflow.com/a/20204635/4433222 しかし、それだけでは不十分でした-苦労した後、私はXMLファイルを見つけましたBOMエンコードなしでUTF-8で保存する必要があります。

このソリューションは、「通常の」UTF-8では機能しませんでした。

0
Konrad