自从我第二次遇到这个烦人的问题以来,我认为询问会有所帮助。
有时我必须从 XML 文档中获取元素,但是这样做的方法很尴尬。
我想知道一个 python 库,它可以做我想做的事,一种优雅的方式来制定我的 XPaths,一种在前缀中自动注册命名空间的方法,或者在内置 XML 实现或 lxml 中隐藏的首选项以剥离命名空间完全地。除非你已经知道我想要什么,否则澄清如下:)
示例文档:
<root xmlns="http://really-long-namespace.uri"
xmlns:other="http://with-ambivalent.end/#">
<other:elem/>
</root>
ElementTree API 是唯一(我知道的)提供 XPath 查询的内置 API。但它要求我使用“UNames”。这看起来像这样:/{http://really-long-namespace.uri}root/{http://with-ambivalent.end/#}elem
如您所见,这些内容非常冗长。我可以通过执行以下操作来缩短它们:
default_ns = "http://really-long-namespace.uri"
other_ns = "http://with-ambivalent.end/#"
doc.find("/{{{0}}}root/{{{1}}}elem".format(default_ns, other_ns))
但这既{{{ugly}}}又脆弱,因为 http…end/# ≃ http…end# ≃ http…end/ ≃ http...end,我有谁知道将使用哪个变体?
另外,lxml 支持命名空间前缀,但它既不使用文档中的前缀,也不提供处理默认命名空间的自动化方式。我仍然需要获取每个命名空间的一个元素才能从文档中检索它。命名空间属性没有保留,因此也无法从这些属性中自动检索它们。
也有一种与命名空间无关的 XPath 查询方式,但在内置实现中它既冗长/丑陋且不可用:/*[local-name() = 'root']/*[local -name() = 'elem']
我想找到一个库、选项或通用 XPath 变形函数来实现上述示例,只需键入以下内容……
/root/elem/root/other:elem...也许还有一些我确实想使用文档前缀或去除命名空间的语句。
进一步说明:虽然我目前的用例就这么简单,但我以后将不得不使用更复杂的用例。
感谢阅读!
用户样本偏见将我的注意力引向 py-dom-xpath ;正是我想要的。我的实际代码现在看起来像这样:
#parse the document into a DOM tree
rdf_tree = xml.dom.minidom.parse("install.rdf")
#read the default namespace and prefix from the root node
context = xpath.XPathContext(rdf_tree)
name = context.findvalue("//em:id", rdf_tree)
version = context.findvalue("//em:version", rdf_tree)
#<Description/> inherits the default RDF namespace
resource_nodes = context.find("//Description/following-sibling::*", rdf_tree)
与文档一致,简单,命名空间感知;完美。
最佳答案
*[local-name() = "elem"] 语法应该可以工作,但为了更容易,您可以创建一个函数来简化部分或完整“通配符命名空间”XPath 的构造表达式。
我在 Ubuntu 10.04 上使用 python-lxml 2.2.4,下面的脚本适用于我。您需要根据要如何为每个元素指定默认命名空间来自定义行为,并处理要折叠到表达式中的任何其他 XPath 语法:
import lxml.etree
def xpath_ns(tree, expr):
"Parse a simple expression and prepend namespace wildcards where unspecified."
qual = lambda n: n if not n or ':' in n else '*[local-name() = "%s"]' % n
expr = '/'.join(qual(n) for n in expr.split('/'))
nsmap = dict((k, v) for k, v in tree.nsmap.items() if k)
return tree.xpath(expr, namespaces=nsmap)
doc = '''<root xmlns="http://really-long-namespace.uri"
xmlns:other="http://with-ambivalent.end/#">
<other:elem/>
</root>'''
tree = lxml.etree.fromstring(doc)
print xpath_ns(tree, '/root')
print xpath_ns(tree, '/root/elem')
print xpath_ns(tree, '/root/other:elem')
输出:
[<Element {http://really-long-namespace.uri}root at 23099f0>]
[<Element {http://with-ambivalent.end/#}elem at 2309a48>]
[<Element {http://with-ambivalent.end/#}elem at 2309a48>]
更新:如果您发现确实需要解析 XPath,您可以查看 py-dom-xpath 等项目这是(大部分)XPath 1.0 的纯 Python 实现。至少这会让您对解析 XPath 的复杂性有所了解。
关于python - 如何以与命名空间无关的方式在 Python 中通过 XPath 查找 XML 元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5572247/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
我使用Nokogiri(Rubygem)css搜索寻找某些在我的html里面。看起来Nokogiri的css搜索不喜欢正则表达式。我想切换到Nokogiri的xpath搜索,因为这似乎支持搜索字符串中的正则表达式。如何在xpath搜索中实现下面提到的(伪)css搜索?require'rubygems'require'nokogiri'value=Nokogiri::HTML.parse(ABBlaCD3"HTML_END#my_blockisgivenmy_bl="1"#my_eqcorrespondstothisregexmy_eq="\/[0-9]+\/"#FIXMEThefoll
当我在我的Rails应用程序根目录中运行rakedoc:app时,API文档是使用/doc/README_FOR_APP作为主页生成的。我想向该文件添加.rdoc扩展名,以便它在GitHub上正确呈现。更好的是,我想将它移动到应用程序根目录(/README.rdoc)。有没有办法通过修改包含的rake/rdoctask任务在我的Rakefile中执行此操作?是否有某个地方可以查找可以修改的主页文件的名称?还是我必须编写一个新的Rake任务?额外的问题:Rails应用程序的两个单独文件/README和/doc/README_FOR_APP背后的逻辑是什么?为什么不只有一个?
我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use
这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。
查看我的Ruby代码:h=Hash.new([])h[0]=:word1h[1]=h[1]输出是:Hash={0=>:word1,1=>[:word2,:word3],2=>[:word2,:word3]}我希望有Hash={0=>:word1,1=>[:word2],2=>[:word3]}为什么要附加第二个哈希元素(数组)?如何将新数组元素附加到第三个哈希元素? 最佳答案 如果您提供单个值作为Hash.new的参数(例如Hash.new([]),完全相同的对象将用作每个缺失键的默认值。这就是您所拥有的,那是你不想要的。您可以改用
我正在学习http://ruby.railstutorial.org/chapters/static-pages上的RubyonRails教程并遇到以下错误StaticPagesHomepageshouldhavethecontent'SampleApp'Failure/Error:page.shouldhave_content('SampleApp')Capybara::ElementNotFound:Unabletofindxpath"/html"#(eval):2:in`text'#./spec/requests/static_pages_spec.rb:7:in`(root)'