libxml2
中是否有任何工具可以让我对齐每个节点的属性? 我有一个很大的 XML 文档,我无法更改其逻辑结构,但我想更改
<a attr="one" bttr="two" tttr="three" fttr="four"/>
进入
<a attr = "one"
bttr = "two"
tttr = "three"
fttr = "four"
longer = "attribute" />
xmllint
有一个选项--pretty
,支持三个级别的漂亮程度。如果这个输出:
<?xml version="1.0"?>
<a
attr="one"
bttr="two"
tttr="three"
fttr="four"
/>
适合你,然后使用
--pretty 2
:
xmllint --pretty 2 - <<< '<a attr="one" bttr="two" tttr="three" fttr="four"/>'
xml_pp
您要求使用 libxml2 中的某些内容。我对此一无所知。但如果您愿意使用其他东西,请继续阅读下文。
xml_pp 是 XML::Twig 库的一部分,并且具有许多不同的预配置样式。
您可以通过“-s”(样式)参数指定样式。
如果您将“-s”留空,那么它将显示所有可用的样式。 (它实际上是动态生成该列表的。因此保证它是最新的。)
$ xml_pp -s
Use of uninitialized value $opt{"style"} in hash element at /usr/bin/xml_pp line 100.
usage: /usr/bin/xml_pp [-v] [-i<extension>] [-s (none|nsgmls|nice|indented|indented_close_tag|indented_c|wrapped|record_c|record|cvs|indented_a)] [-p <tag(s)>] [-e <encoding>] [-l] [-f <file>] [<files>] at /usr/bin/xml_pp line 100.
这又是同样的事情,但列表格式更好。 原来我安装的版本开箱即支持11种格式:
$ xml_pp -s 2>&1 | grep -Po '(?<=\[-s \()[^)]*' -o | tr '|' '\n' | nl
1 none
2 nsgmls
3 nice
4 indented
5 indented_close_tag
6 indented_c
7 wrapped
8 record_c
9 record
10 cvs
11 indented_a
所以让我们全部尝试一下。
这是我们的输入文件:
$ cat in.xml
<a attr="one" bttr="two" tttr="three" fttr="four"/>
这些是所有款式:
$ for STYLE in $(echo "none nsgmls nice indented indented_close_tag indented_c wrapped record_c record cvs indented_a"); do echo; echo "==> Style: xml_pp -s $STYLE <=="; cat in.xml | xml_pp -s $STYLE | tee out.xml_pp.$STYLE.xml; echo; done
==> Style: xml_pp -s none <==
<a attr="one" bttr="two" fttr="four" tttr="three"/>
==> Style: xml_pp -s nsgmls <==
<a
attr="one"
bttr="two"
fttr="four"
tttr="three"
/>
==> Style: xml_pp -s nice <==
<a attr="one" bttr="two" fttr="four" tttr="three"/>
==> Style: xml_pp -s indented <==
<a attr="one" bttr="two" fttr="four" tttr="three"/>
==> Style: xml_pp -s indented_close_tag <==
<a attr="one" bttr="two" fttr="four" tttr="three"/>
==> Style: xml_pp -s indented_c <==
<a attr="one" bttr="two" fttr="four" tttr="three"/>
==> Style: xml_pp -s wrapped <==
<a attr="one" bttr="two" fttr="four" tttr="three"/>
==> Style: xml_pp -s record_c <==
<a attr="one" bttr="two" fttr="four" tttr="three"/>
==> Style: xml_pp -s record <==
<a attr="one" bttr="two" fttr="four" tttr="three"/>
==> Style: xml_pp -s cvs <==
<a
attr="one"
bttr="two"
fttr="four"
tttr="three"
/>
==> Style: xml_pp -s indented_a <==
<a
attr="one"
bttr="two"
fttr="four"
tttr="three"
/>
对于这个小输入文件来说,这些样式中的一堆是等效的。 它们产生相同的输出:
$ sha256sum * | sort
452f5c19177d9cc6a54589168dbb1ee790c783a963110662e7dfae170bf997e4 out.xml_pp.cvs.xml
452f5c19177d9cc6a54589168dbb1ee790c783a963110662e7dfae170bf997e4 out.xml_pp.indented_a.xml
8e119bb50bcbf3d72159c96139cf328f46a0de259410acdd344f26e52f033996 out.xml_pp.nsgmls.xml
d1ed9a4d1ebf8b9f1d012577809909e91e1ba0fc01b5afc8ff1302ca9dced617 out.xml_pp.record_c.xml
d1ed9a4d1ebf8b9f1d012577809909e91e1ba0fc01b5afc8ff1302ca9dced617 out.xml_pp.record.xml
e0d13f80ddc48876678c62e407abd3ab1eac8481a82d5aabb1514e24aee4717c in.xml
ea90003eab0ba71936a8a329a87b079b4fb120fe6873d4fa9bc8f986e8654b45 out.xml_pp.indented_close_tag.xml
ea90003eab0ba71936a8a329a87b079b4fb120fe6873d4fa9bc8f986e8654b45 out.xml_pp.indented_c.xml
ea90003eab0ba71936a8a329a87b079b4fb120fe6873d4fa9bc8f986e8654b45 out.xml_pp.indented.xml
ea90003eab0ba71936a8a329a87b079b4fb120fe6873d4fa9bc8f986e8654b45 out.xml_pp.nice.xml
ea90003eab0ba71936a8a329a87b079b4fb120fe6873d4fa9bc8f986e8654b45 out.xml_pp.none.xml
ea90003eab0ba71936a8a329a87b079b4fb120fe6873d4fa9bc8f986e8654b45 out.xml_pp.wrapped.xml
这些风格都不是你想要的。
但是“cvs”非常接近。 (“indented_a”产生相同的输出。)
事后思考:输出感觉有点脏。
(a) 有些文件无缘无故地以空行开头...
$ grep '^$' * -n
out.xml_pp.record_c.xml:1:
out.xml_pp.record.xml:1:
(b) ...有些文件根本没有行终止符:
$ file *
in.xml: ASCII text
out.xml_pp.cvs.xml: ASCII text
out.xml_pp.indented_a.xml: ASCII text
out.xml_pp.indented_close_tag.xml: ASCII text, with no line terminators
out.xml_pp.indented_c.xml: ASCII text, with no line terminators
out.xml_pp.indented.xml: ASCII text, with no line terminators
out.xml_pp.nice.xml: ASCII text, with no line terminators
out.xml_pp.none.xml: ASCII text, with no line terminators
out.xml_pp.nsgmls.xml: ASCII text
out.xml_pp.record_c.xml: ASCII text
out.xml_pp.record.xml: ASCII text
out.xml_pp.wrapped.xml: ASCII text, with no line terminators
-- 问题似乎是 xml_pp 没有在最后一行之后添加尾随换行符。因此,如果只有一行,那么其中将不会有换行字节。很奇怪。
看起来像这样:
$ wc --lines *
5 out.xml_pp.cvs.xml
5 out.xml_pp.indented_a.xml
0 out.xml_pp.indented_close_tag.xml
0 out.xml_pp.indented_c.xml
0 out.xml_pp.indented.xml
0 out.xml_pp.nice.xml
0 out.xml_pp.none.xml
5 out.xml_pp.nsgmls.xml
1 out.xml_pp.record_c.xml
1 out.xml_pp.record.xml
0 out.xml_pp.wrapped.xml
17 total
这就是我喜欢添加尾随 LF(0x0A 字节)(如果不存在的话)的方式:
$ mkdir 1; mv out.*.xml 1/; cp -r 1/ 2/
$ pcregrep -LMr '\n\Z' 2/ | xargs -n1 --no-run-if-empty -- sed -i -e '$a\' --
$ diff --recursive 1/ 2/ | head
diff --recursive 1/out.xml_pp.cvs.xml 2/out.xml_pp.cvs.xml
6c6
< />
\ No newline at end of file
---
> />
diff --recursive 1/out.xml_pp.indented_a.xml 2/out.xml_pp.indented_a.xml
6c6
< />
\ No newline at end of file
之后看起来像这样:
$ cd 2/
$ wc --lines *
6 out.xml_pp.cvs.xml
6 out.xml_pp.indented_a.xml
1 out.xml_pp.indented_close_tag.xml
1 out.xml_pp.indented_c.xml
1 out.xml_pp.indented.xml
1 out.xml_pp.nice.xml
1 out.xml_pp.none.xml
6 out.xml_pp.nsgmls.xml
2 out.xml_pp.record_c.xml
2 out.xml_pp.record.xml
1 out.xml_pp.wrapped.xml
28 total