是否有一个针对Ubuntu和/或CentOS的包,它有一个命令行工具,可以执行像foo //element@attribute filename.xml或foo //element@attribute < filename.xml这样的XPath一行程序,并逐行返回结果?
我正在寻找一些东西,这将允许我只是apt-get安装foo或yum安装foo,然后只是开箱即用,没有包装或其他必要的适应。
以下是一些很接近的例子:
Nokogiri。如果我写这个包装器,我可以用上面描述的方式调用包装器:
#!/usr/bin/ruby
require 'nokogiri'
Nokogiri::XML(STDIN).xpath(ARGV[0]).each do |row|
puts row
end
XML:: XPath。将与此包装工作:
#!/usr/bin/perl
use strict;
use warnings;
use XML::XPath;
my $root = XML::XPath->new(ioref => 'STDIN');
for my $node ($root->find($ARGV[0])->get_nodelist) {
print($node->getData, "\n");
}
xpath从XML:: xpath返回太多噪音,——NODE——和attribute = "value"。
来自XML::Twig的xml_grep不能处理不返回元素的表达式,因此不能在没有进一步处理的情况下用于提取属性值。
编辑:
Echo cat //element/@attribute | xmllint——shell filename.xml返回类似xpath的噪声。
Xmllint——xpath //element/@attribute filename.xml返回attribute = "value"。
xmllint——xpath 'string(//element/@attribute)' filename.xml返回我想要的,但只对第一个匹配。
对于另一个几乎可以满足这个问题的解决方案,下面是一个可以用于计算任意XPath表达式的XSLT(需要XSLT处理器中的dyn:evaluate支持):
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:dyn="http://exslt.org/dynamic" extension-element-prefixes="dyn">
<xsl:output omit-xml-declaration="yes" indent="no" method="text"/>
<xsl:template match="/">
<xsl:for-each select="dyn:evaluate($pattern)">
<xsl:value-of select="dyn:evaluate($value)"/>
<xsl:value-of select="' '"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
使用xsltproc——stringparam pattern //element/@attribute——stringparam value运行。arbitrary-xpath。xslt filename.xml。
A minimal wrapper for python's lxml module that will print all matching nodes by name (at any level), e.g. mysubnode or an XPath subset e.g. //intermediarynode/subnode. If the expression evaluates to text then text will be printed, if it evaluates to an element then the entire raw element will be rendered to text. It also attempts to handle XML namespaces in a way that allows using local tag names without prefixing. With extended XPath mode enabled via the -x flag the default namespace needs to be referenced with the p: prefix, e.g. //p:tagname/p:subtag
#!/usr/bin/env python3
import argparse
import os
import sys
from lxml import etree
DEFAULT_NAMESPACE_KEY = 'p'
def print_element(elem):
if isinstance(elem, str):
print(elem)
elif isinstance(elem, bytes):
print(elem.decode('utf-8'))
else:
print(elem.text and elem.text.strip() or etree.tostring(elem, encoding='unicode', pretty_print=True))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='XPATH lxml wrapper',
usage="""
Print all nodes by name in XML file:
\t{0} myfile.xml somename
Print all nodes by XPath selector (findall: reduced subset):
\t{0} myfile.xml //itermediarynode/childnode
Print attribute values by XPath selector 'p' maps to default namespace (xpath 1.0: extended subset):
\t{0} myfile.xml //p:itermediarynode/p:childnode/@src -x
""".format(os.path.basename(sys.argv[0])))
parser.add_argument('xpath_file',
help='XPath file path')
parser.add_argument('xpath_expression',
help='tag name or xpath expression')
parser.add_argument('--force_xpath', '-x',
action='store_true',
default=False,
help='Use lxml.xpath (rather than findall)'
)
args = parser.parse_args(sys.argv[1:])
xpath_expression = args.xpath_expression
tree = etree.parse(args.xpath_file)
ns = tree.getroot().nsmap
if args.force_xpath:
if ns.keys() and None in ns:
ns[DEFAULT_NAMESPACE_KEY] = ns.pop(None)
for node in tree.xpath(xpath_expression, namespaces=ns):
print_element(node)
elif xpath_expression.isalpha():
for node in tree.xpath(f"//*[local-name() = '{xpath_expression}']"):
print_element(node)
else:
for el in tree.findall(xpath_expression, namespaces=ns):
print_element(el)
它使用lxml -一个用C编写的快速XML解析器,它不包含在标准python库中。使用pip Install lxml安装它。在Linux/OSX上可能需要用sudo作为前缀。
用法:
python3 xmlcat.py file.xml "//mynode"
lxml也可以接受URL作为输入:
python3 xmlcat.py http://example.com/file.xml "//mynode"
提取框节点下的url属性,即<enclosure url="http:…""..>)(-x强制扩展XPath 1.0子集):
python3 xmlcat.py xmlcat.py file.xml "//enclosure/@url" -x
在谷歌Chrome中的Xpath
作为一个无关的边注:如果碰巧你想运行一个XPath表达式对网页的标记,那么你可以直接从Chrome devtools:右键单击页面在Chrome >选择检查,然后在devtools控制台粘贴你的XPath表达式为$x("//spam/eggs")。
获取本页上的所有作者:
$x("//*[@class='user-details']/a/text()")