2

lxml で解析中に外部の未解析エンティティを解決するにはどうすればよいですか?

これが私のコード例です:

import io

from lxml import etree

content = b"""\
<?xml version="1.0"?>
<!DOCTYPE sample [
<!NOTATION jpeg SYSTEM "image/jpeg">
<!ENTITY ref1 SYSTEM "python-logo-small.jpg" NDATA jpeg>
<!ELEMENT sample EMPTY>
<!ATTLIST sample src ENTITY #REQUIRED>
]>
<sample src="ref1"/>
"""

parser = etree.XMLParser(dtd_validation=True, resolve_entities=True)
doc = etree.parse(io.BytesIO(content), parser=parser)
print(etree.tostring(doc))

注: lxml >= 3.4 を使用しています

現在、次の結果があります。

<!DOCTYPE sample [
<!NOTATION jpeg SYSTEM "image/jpeg" >
<!ENTITY ref1 SYSTEM "python-logo-small.jpg" NDATA jpeg>
<!ELEMENT sample EMPTY>
<!ATTLIST sample src ENTITY #REQUIRED>
]>
<sample src="ref1"/>

ここでは、ref1エンティティは「python-logo-small.jpg」に解決されていません。私は持っていると思ってい<sample src="python-logo-small.jpg"/>ました。何か問題がありますか?

私も試してみます:

parser = etree.XMLParser(dtd_validation=True, resolve_entities=True, load_dtd=True)

しかし、私は同じ結果を持っています。

または、エンティティを自分で再ソールしたいと思います。そのために、エンティティを次のようにリストします。

for entity in doc.docinfo.internalDTD.iterentities():
    msg_fmt = "{entity.name!r}, {entity.content!r}, {entity.orig!r}"
    print(msg_fmt.format(entity=entity))

しかし、エンティティの定義ではなく、エンティティと表記の名前のみを取得します。

'ref1', 'jpeg', None

エンティティの定義にアクセスするには?

4

2 に答える 2

0

解析されていないエンティティを含む XML ドキュメントは正常に見えます。しかし、解析されていないエンティティは、期待どおりに解決されません。<sample src="python-logo-small.jpg"/>解析された出力を確認したい場合は、内部 (解析済み) エンティティを使用します。

例:

import io
from lxml import etree

content = b"""\
<?xml version="1.0"?>
<!DOCTYPE sample [
<!ENTITY ref1 "python-logo-small.jpg">
<!ELEMENT sample EMPTY>
<!ATTLIST sample src CDATA #REQUIRED>
]>
<sample src="&ref1;"/>
"""

parser = etree.XMLParser(dtd_validation=True, resolve_entities=True)
doc = etree.parse(io.BytesIO(content), parser=parser)
print(etree.tostring(doc))

出力:

<!DOCTYPE sample [
<!ENTITY ref1 "python-logo-small.jpg">
<!ELEMENT sample EMPTY>
<!ATTLIST sample src CDATA #REQUIRED>
]>
<sample src="python-logo-small.jpg"/>

ノート:

  • ref1エンティティは内部エンティティとして宣言されます。
  • エンティティは で参照され&ref1;ます。
  • src属性は type として宣言されますCDATA

関数を使用して、XSLT で解析されていないエンティティの値 (URI) を取得できますunparsed-entity-uri。実際の動作を確認するには、質問のコード例に次の行を追加します。

xsl = etree.XML('''\
<xsl:stylesheet version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output encoding="utf-8" omit-xml-declaration="yes"/>
 <xsl:template match="sample">
   <xsl:value-of select="unparsed-entity-uri(@src)"/>
 </xsl:template>
</xsl:stylesheet>
''')

transform = etree.XSLT(xsl)
result = transform(doc)
print result

出力:

python-logo-small.jpg
于 2015-09-24T12:00:23.193 に答える
0

OK、解析されていない外部エンティティを「解決」することはできませんが、それらをリストすることはできます。

import io

import xml.sax

content = b"""\
<?xml version="1.0"?>
<!DOCTYPE sample [
<!NOTATION jpeg SYSTEM "image/jpeg">
<!ENTITY ref1 SYSTEM "python-logo-small.jpg" NDATA jpeg>
<!ELEMENT sample EMPTY>
<!ATTLIST sample src ENTITY #REQUIRED>
]>
<sample src="ref1"/>
"""


class MyDTDHandler(xml.sax.handler.DTDHandler):
    def __init__(self):
        pass

    def unparsedEntityDecl(self, name, publicId, systemId, ndata):
        print(dict(name=name, publicId=publicId, systemId=systemId, ndata=ndata))
        xml.sax.handler.DTDHandler.unparsedEntityDecl(self, name, publicId, systemId, ndata)


parser = xml.sax.make_parser()
parser.setDTDHandler(MyDTDHandler())
parser.parse(io.BytesIO(content))

結果は次のとおりです。

{'systemId': u'python-logo-small.jpg', 'ndata': u'jpeg', 'publicId': None, 'name': u'ref1'}

これで作業は完了です。

于 2015-09-24T12:59:24.180 に答える