我正在处理一个 XML 文档,其中标签必须具有一组属性或另一组属性。例如,它需要看起来像<tag foo="hello" bar="kitty" />或<tag spam="goodbye" eggs="world" />例如
<root>
<tag foo="hello" bar="kitty" />
<tag spam="goodbye" eggs="world" />
</root>
Run Code Online (Sandbox Code Playgroud)
所以我有一个 XSD 架构,我使用该xs:choice元素在两个不同的属性组之间进行选择:
<xsi:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema" attributeFormDefault="unqualified" elementFormDefault="qualified">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="tag">
<xs:choice>
<xs:complexType>
<xs:attribute name="foo" type="xs:string" use="required" />
<xs:attribute name="bar" type="xs:string" use="required" />
</xs:complexType>
<xs:complexType>
<xs:attribute name="spam" type="xs:string" use="required" />
<xs:attribute name="eggs" type="xs:string" use="required" />
</xs:complexType>
</xs:choice>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xsi:schema>
Run Code Online (Sandbox Code Playgroud)
但是,当使用lxml尝试加载此架构时,出现以下错误:
>>> from lxml import etree
>>> …Run Code Online (Sandbox Code Playgroud) 有没有办法从 lxml 的 lxml.etree.iterparse 中获取多个标签名称?我有一个类似文件的对象,它具有昂贵的读取操作和许多标签,因此获取所有标签或执行两次传递是次优的。
编辑:它类似于 Beautiful Soup's find(['tag-1', 'tag-2]),除了作为 iterparse 的参数。想象一下为<td>和<div>标签解析 HTML 页面。
假设我有以下xml:
<package xmlns="http://example/namespace">
<rating system="au-oflc">PG</rating>
...
</package>
Run Code Online (Sandbox Code Playgroud)
要获取上面元素的文本,我将执行以下操作:
from lxml import entree
f = open('/Users/David/Desktop/metadata.xml')
metadata_contents = f.read()
node = etree.fromstring(metadata_contents)
rating = node.xpath('//t:rating/text()', namespaces = {'t':'http://example/namespace'})
>>> rating
['PG']
Run Code Online (Sandbox Code Playgroud)
我怎样才能获得"au-oflc"的价值?
我一直在使用lxml和formalchemy为sqlalchemy构建一个脚手架库,我很难让他们玩得很好.具体来说,formalchemy.FieldSet.render()返回一个没有root标签的html片段,我似乎无法弄清楚如何让lxml将其解析成可以包含在元素树中的东西:
我得到了什么:
>>> lxml.etree.fromstring(formalchemy.FieldSet(toyschema.User(), session).render())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "lxml.etree.pyx", line 2743, in lxml.etree.fromstring (src/lxml/lxml.etree.c:52665)
File "parser.pxi", line 1573, in lxml.etree._parseMemoryDocument (src/lxml/lxml.etree.c:79932)
File "parser.pxi", line 1445, in lxml.etree._parseDoc (src/lxml/lxml.etree.c:78709)
File "parser.pxi", line 920, in lxml.etree._BaseParser._parseUnicodeDoc (src/lxml/lxml.etree.c:75083)
File "parser.pxi", line 564, in lxml.etree._ParserContext._handleParseResultDoc (src/lxml/lxml.etree.c:71739)
File "parser.pxi", line 645, in lxml.etree._handleParseResult (src/lxml/lxml.etree.c:72614)
File "parser.pxi", line 585, in lxml.etree._raiseParseError (src/lxml/lxml.etree.c:71955)
lxml.etree.XMLSyntaxError: Extra content at the end of the document, line 8, column 1 …Run Code Online (Sandbox Code Playgroud) 我有一个具有以下结构的 xml 文件:
<main_tag>
<first>
<tag1>val1</tag1>
<conf>
<tag2>val2</tag2>
<tag3>val3</tag3>
<tag4>val4</tag4>
</conf>
</first>
<second>
<tag1>val2</tag1>
<conf>
<tag2>val6</tag2>
<tag3>val7</tag3>
<tag4>val8</tag4>
</conf>
</second>
</main_tag>
Run Code Online (Sandbox Code Playgroud)
我必须更改 tag2 的值。可能的值存储在字典中:
{tag2values:[newvalue1, newvalue2]}
Run Code Online (Sandbox Code Playgroud)
如果 tag1 的值为 val1,那么我们将 tag2 的值更改为 newvalue1。如果 tag1 值为 val2,那么我们将 tag2 值更改为 newvalue2。
所以问题是:有没有办法在 lxml 中找到与其父值匹配的元素?或者通过它的父邻居值找到一个元素?
给出以下xml:
<!-- file.xml -->
<video>
<original_spoken_locale>en-US</original_spoken_locale>
<another_tag>somevalue</another_tag>
</video>
Run Code Online (Sandbox Code Playgroud)
替换<original_spoken_locale>标签内部值的最佳方法是什么?如果我确实知道价值,我可以使用类似的东西:
with open('file.xml', 'r') as file:
contents = file.read()
new_contents = contents.replace('en-US, 'new-value')
with open('file.xml', 'w') as file:
file.write(new_contents)
Run Code Online (Sandbox Code Playgroud)
但是,在这种情况下,我不知道它的价值.
使用 lxml 渲染 XHTML 时,一切都很好,除非您碰巧使用 Firefox,它似乎无法处理以命名空间为前缀的 XHTML 元素和 javascript。虽然Opera是能够执行JavaScript(这适用于jQuery和MathJax)的罚款,无论XHTML命名空间是否具有前缀(h:在我的情况)或没有,Firefox中的脚本将用奇怪的错误(中止this.head是未定义的MathJax 的情况)。
我知道这个register_namespace函数,但它既不接受None也不""作为命名空间前缀。我_namespace_map在lxml.etree模块中听说过,但是我的 Python 抱怨这个属性不存在(版本问题?)
有没有其他方法可以删除 XHTML 名称空间的名称空间前缀?请注意str.replace,正如在另一个相关问题的回答中所建议的那样,不是我可以接受的方法,因为它不知道 XML 语义并且可能很容易搞砸结果文档。
根据请求,您会发现两个可以使用的示例。一种带有命名空间前缀,一种没有. 第一个将在 Firefox 中显示 0(错误),第二个将显示 1(正确)。Opera 将正确呈现两者。这显然是一个 Firefox 错误,但这只是作为想要使用 lxml 的无前缀 XHTML 的一个基本原理——还有其他很好的理由来减少移动客户端的流量等(h:如果你考虑数十或数百个 html 标签,甚至很多) .
如何获取包含一段文本的节点的父节点?
此外,我可以使用一些正则表达式机制作为搜索/过滤的匹配元素re.compile("th[ei]s? .ne"),例如下面的搜索吗?
说 this one
html = '''<html>
<head><title></title></head>
<body>
<table>
<tr><td>1a</td><td>2a</td><td>3a</td><td>4a</td><td>5a</td><td>6a</td></tr>
<tr><td>1b</td><td>2b</td><td>3b</td><td>4b</td><td>5b</td><td>6b</td></tr>
<tr><td>1c</td><td>2c</td><td>3c</td><td>4c</td><td>5c</td><td>6c this one</td></tr>
</table>
<div><div>
<table>
<tr><td>1A</td><td>2A</td><td>3A</td><td>4A</td><td>5A</td><td>6A</td></tr>
<tr><td>1B</td><td>2B</td><td>3B</td><td>4B</td><td>5B</td><td>6B</td></tr>
<tr><td>1C</td><td>2C</td><td>3C</td><td>4C</td><td>5C</td><td>6C</td></tr>
</table>this one
</div></div>
</body>
</html>'''
Run Code Online (Sandbox Code Playgroud)
我想要一个返回的迭代器:
<td>6c this one</td>
Run Code Online (Sandbox Code Playgroud)
进而:
<div>
<table>
<tr><td>1A</td><td>2A</td><td>3A</td><td>4A</td><td>5A</td><td>6A</td></tr>
<tr><td>1B</td><td>2B</td><td>3B</td><td>4B</td><td>5B</td><td>6B</td></tr>
<tr><td>1C</td><td>2C</td><td>3C</td><td>4C</td><td>5C</td><td>6C</td></tr>
</table>this one
</div>
Run Code Online (Sandbox Code Playgroud)
我试过:
import lxml.html
root = lxml.html.document_fromstring(html)
root.xpath("//text()[contains(., one)]")
Run Code Online (Sandbox Code Playgroud)
和
import xml.etree.ElementTree as ET
for e in ET.fromstring(html).getiterator():
if e.text and e.text.find('one') != -1:
print "Found string %r, element = %r" % (e.text, e)
Run Code Online (Sandbox Code Playgroud)
但我能拥有的最好的是包含this one自身的节点......而我正在寻找包含此文本的父节点。请注意,div …
我有一个脚本来解析一个html文件,该脚本运行得很好,直到我对其稍作更改,从而可以从终端运行它,如下所示:
python myscript.py filename
Run Code Online (Sandbox Code Playgroud)
因此,当指示要解析的文件的直接名称时,它将起作用:
tree = etree.parse("folder/filename.html")
places = []
def f1():
for dfn in tree.getiterator('dfn'):
...
return places
def main():
f1()
file_places = open('list_places.txt', 'w')
for x in sorted(places):
print>>file_places, x
Run Code Online (Sandbox Code Playgroud)
然后,我没有指定文件的确切名称,而是指定了一个变量,然后该变量应在命令行中用作参数:
args=sys.argv[1:]
filename = sys.argv[0]
tree = etree.parse(filename)
places = []
def extract_places():
for dfn in tree.getiterator('dfn'):
...
return places
def main():
if len(args) < 1:
print 'usage: extract.py [file ...]'
sys.exit(1)
else:
extract_places()
file_places = open('list_places.txt', 'w')
for x in sorted(places):
print>>file_places, x
Run Code Online (Sandbox Code Playgroud)
这是我得到的错误:追溯(最近一次呼叫过去):
File "extract.py", …Run Code Online (Sandbox Code Playgroud) 无论如何,我可以让python点击一个链接,如bit.ly链接,然后刮取结果链接?当我抓取某个页面时,我可以抓取的唯一链接是重定向的链接,重定向到的链接是我需要的信息所在的位置.
lxml ×10
python ×10
xml ×4
parsing ×2
elementtree ×1
formalchemy ×1
namespaces ×1
schema ×1
validation ×1
web-scraping ×1
xhtml ×1
xml.etree ×1
xpath ×1
xslt ×1