サニタイズされていないユーザー投稿コンテンツを含むことができる外部ソースから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が文句を言わないようにする方法はありますか?
\x08
エスケープする必要があります。
編集:
または、recover
を使用してパーサーにエラーを無視させることができます
from lxml import etree
parser = etree.XMLParser(recover=True)
etree.fromstring(xmlstring, parser=parser)
同じエラーが発生していました(ElementTreeを使用)。私の場合、これはエンコーディングが原因であり、外部ライブラリを使用せずに解決できました。これが、タイトルに基づいて他の人がこの質問を見つけるのに役立つことを願っています。 ( 参照 )
import xml.etree.ElementTree as ET
parser = ET.XMLParser(encoding="utf-8")
tree = ET.fromstring(xmlstring, parser=parser)
[〜#〜] edit [〜#〜]:コメントに基づいて、この答えは時代遅れかもしれません。しかし、これは答えられたときに元に戻りました...
上記の修正はどれもうまくいきませんでした。動作したのは、次のようにBeautifulSoup
の代わりにElementTree
を使用することだけでした。
from bs4 import BeautifulSoup
with open("data/myfile.xml") as fp:
soup = BeautifulSoup(fp, 'xml')
次に、ツリーを次のように検索できます。
soup.find_all('mytag')
私は同様の問題に悩まされています。最後に、私の特定のケースで根本的な原因が何であるかを見つけました。同じフォルダにある複数のXMLファイルからデータを読み取る場合、.DS_Storeファイルも解析します。解析する前にこの条件を追加してください
for file in files:
if file.endswith('.xml'):
run_your_code...
このトリックは私にも役立ちました
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」は無効です。
私のために働いた唯一のことは、以下のようにファイルを開くときにモードとエンコーディングを追加する必要があったことです:
with open(filenames[0], mode='r',encoding='utf-8') as f:
readFile()
そうしないと、単にこれを行うと、無効なトークンエラーで毎回失敗しました:
f = open(filenames[0], 'r')
readFile()
私はここの答えで他の解決策を試しましたが、運がありませんでした。単一の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]+")
これはおそらくエンコードエラーです。たとえば、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」を変更します。
そのエラーで私を助けたのはJuanの答えでした- https://stackoverflow.com/a/20204635/4433222 しかし、それだけでは不十分でした-苦労した後、私はXMLファイルを見つけましたBOMエンコードなしでUTF-8で保存する必要があります。
このソリューションは、「通常の」UTF-8では機能しませんでした。