如何格式化 XML 文档以使其易于读取元素属性?
我有一个基于 xml 的 Web 服务,它返回一两个元素,但具有数百个属性。当我进行开发时,有时需要调试此服务,但这可能很困难,因为输出只是一个 blob。
考虑一下:
$ echo '<root><foo z="26" y="25" x="24" a="1" b="2" c="3" d="something more"/></root>' | xmllint --format -
<?xml version="1.0"?>
<root>
<foo z="26" y="25" x="24" a="1" b="2" c="3" d="something more"/>
</root>
我发现 tr 效果很好,但并不理想:
$ echo '<root><foo z="26" y="25" x="24" a="1" b="2" c="3" d="something more"/></root>' | xmllint --format - | tr ' ' \\\n
<?xml
version="1.0"?>
<root>
<foo
z="26"
y="25"
x="24"
a="1"
b="2"
c="3"
d="something
more"/>
</root>
理想情况下,输出将介于 xmllint 和时髦的 hack 之间
<?xml version="1.0"?>
<root>
<foo
z="26"
y="25"
x="24"
a="1"
b="2"
c="3"
d="something more"/>
</root>
这样我就可以 grep 查找东西,或者排序等等。
答案1
我强烈建议不要使用 grep/sed - 它们不适用于 XML。
但幸运的是,perl
并且XML::Twig
拥有各种神奇的功能,可以根据您的意愿重新格式化和提取值。get_xpath
非常适合提取值,或者您必须twig_handlers
根据用例处理元素。 (或者只是迭代使用children
或类似)。
但无论如何 - 格式化您的 XML:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
my $twig = XML::Twig->new(
pretty_print => 'nsgmls',
);
$twig->parse (\*DATA);
$twig->print;
__DATA__
<?xml version="1.0"?>
<root>
<foo
z="26"
y="25"
x="24"
a="1"
b="2"
c="3"
d="something more"/>
</root>
在nsgmls
印刷中,这给出:
<?xml version="1.0"?>
<root
><foo
a="1"
b="2"
c="3"
d="something more"
x="24"
y="25"
z="26"
/></root>
indented_a
给你:
<?xml version="1.0"?>
<root>
<foo
a="1"
b="2"
c="3"
d="something more"
x="24"
y="25"
z="26"
/>
</root>
这似乎与您正在寻找的非常接近?
答案2
您可以使用出色的 BeautifulSoup Python 库。此代码示例从作为脚本输入参数给出的 URL 检索 XML 文件,使用 LXML 解析它,然后漂亮地打印它。
#!/usr/bin/env python
import sys
import urllib2
import bs4
soup = bs4.BeautifulSoup(urllib2.urlopen(sys.argv[1]), ["lxml", "xml"])
print(soup.prettify())
如果您无权访问 LXML,您可以尝试 without ["lxml", "xml"]
,尽管这会将数据解析为 HTML 而不是 XML,并且不是正确的方法。