33

サニタイズされていないユーザー提供コンテンツを含む可能性のある外部ソースからxml文字列を受け取ります。

次のxml文字列は次のようにParseErrorを与えました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

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

4

13 に答える 13

34

\x08それはあなたがそれを逃れる必要があるだろうと不平を言うようです。

編集:

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

from lxml import etree
parser = etree.XMLParser(recover=True)
etree.fromstring(xmlstring, parser=parser)
于 2012-10-24T09:25:11.857 に答える
27

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

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

編集:コメントに基づいて、この回答は古くなっている可能性があります。しかし、それが答えられたとき、これはうまくいきました...

于 2013-11-25T22:24:57.473 に答える
7

別の質問に対するこの回答と、XML仕様の対応する部分を参照してください。

バックスペースU+0008は、XMLドキュメントでは無効な文字です。エスケープされたエンティティとして表す必要があり、&#8;わかりやすく表示することはできません。

このXMLスニペットを処理する必要がある場合は、XMLパーサーにフィードする前に\x08置き換える必要があります。s

于 2012-10-24T09:35:26.873 に答える
7

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

from bs4 import BeautifulSoup

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

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

soup.find_all('mytag')
于 2018-05-08T10:56:24.530 に答える
4

このコードスニペットは私のために働いた。XMLファイルのバッチの解析に問題があります。それらを「iso-8859-5」にエンコードする必要がありました

import xml.etree.ElementTree as ET

tree = ET.parse(filename, parser = ET.XMLParser(encoding = 'iso-8859-5'))
于 2020-02-25T19:24:18.050 に答える
3

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のドキュメントでこの脚注を見つけました:

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

于 2017-09-06T19:35:48.897 に答える
3

これはおそらくエンコーディングエラーです。たとえば、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」を変更します。

于 2018-02-13T14:29:09.520 に答える
2

WWW全体を何度も検索した結果、XMLパーサーを機能させるには、特定の文字をエスケープする必要があることがわかりました。これが私がそれをして私のために働いた方法です:

escape_illegal_xml_characters = lambda x: re.sub(u'[\x00-\x08\x0b\x0c\x0e-\x1F\uD800-\uDFFF\uFFFE\uFFFF]', '', x)

そして、通常どおりに使用します。

ET.XML(escape_illegal_xml_characters(my_xml_string)) #instead of ET.XML(my_xml_string)
于 2019-12-13T09:57:01.700 に答える
1

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

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

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

于 2017-06-23T19:38:21.527 に答える
1

私の場合、lxmlが問題を解決しました

from lxml import etree

for _, elein etree.iterparse(xml_file, tag='tag_i_wanted', unicode='utf-8'):
    print(ele.tag, ele.text)  

別のケースでは、

parser = etree.XMLParser(recover=True)
tree = etree.parse(xml_file, parser=parser)
tags_needed = tree.iter('TAG NAME')

東海岸のおかげで

Python 2.7

于 2019-10-24T05:49:26.527 に答える
0

そのエラーで私を助けたのは、Juanの答えでした-https://stackoverflow.com/a/20204635/4433222 しかし、十分ではありませんでした-苦労した後、XMLファイルをBOMエンコーディングなしでUTF-8で保存する必要があることがわかりました。

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

于 2016-02-05T10:20:02.003 に答える
0

私のために働いた唯一のことは、以下のようにファイルを開いている間にモードとエンコーディングを追加しなければならなかったことです:

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

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

 f = open(filenames[0], 'r')
 readFile()
于 2019-08-29T18:28:44.573 に答える
-1

私はここの答えで他の解決策を試しましたが、運がありませんでした。与えた単一の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]+")
于 2018-09-06T13:36:28.190 に答える