0

我有很多(超过 50 个)xml 文件,其中一些行(每个文件超过 30/40 个)格式不正确:

例如,这个:

<TAG1>
    <TAG_TO_FORMAT>
           a_random_string

    </TAG_TO_FORMAT>
    <AN_OTHER_TAG_TO_FORMAT>
                       an_other_random_string
    </AN_OTHER_TAG_TO_FORMAT>
    <OTHER_TAG>pifpafpouf</OTHER_TAG>

</TAG1>

应该变成这样:

<TAG1>
    <TAG_TO_FORMAT>a_random_string</TAG_TO_FORMAT>
    <AN_OTHER_TAG_TO_FORMAT>an_other_random_string</AN_OTHER_TAG_TO_FORMAT>
    <OTHER_TAG>pifpafpouf</OTHER_TAG>

</TAG1>

之前的新行是否仍然存在并不重要</TAG1>,我的关键问题是每个模式:<TAG>random_string</TAG>必须在一行上(random_string 不包含 EOL)

我在 bash 中找不到任何允许我执行此操作的工具,那么我如何在 bash 中执行此操作?(或者也许在 python 中,但我更喜欢 bash)。

4

4 回答 4

7

有像 xmllint 和 tidy 这样的命令行工具可以像这样使用:

tidy -xml -iq somefile.xml

理论上 xmllint 也可以做到,但 xmllint 在 OS X 上不能像我描述的那样工作(目前没有方便的 Linux 实例在那里测试):

xmllint --noblanks somefile.xml
于 2013-04-10T18:53:40.340 回答
0

I'd recommend Perl for this kind of task.

#!/usr/bin/env perl

use strict;
use warnings;

my $text = join "", <>; 
$text =~ s/>\s+([^\s].*?[^\s])\s+<\//>$2<\//;
print "$text";

Call it like this:

my.pl < input.xml > output.xml
于 2013-04-10T18:17:57.803 回答
0

好吧,你可以在 sed 中做到这一点:

x='TAG_TO_FORMAT'
sed -e '/<'"$x"'>/{:next;/<\/'"$x"'>/!{N;bnext;};s/\n//g;s/>\s*/>/;s/\S\s*</</;}'

当一行以正确的标签开始时,我们进入一个循环收集行,直到找到结束标签。然后我们删除所有换行符并清理由 > 一侧和 < 在另一侧锚定的空格。

于 2013-04-10T18:38:36.510 回答
0

整洁的工作是合理的。另一种选择是调用 normalize-space() 的 xslt 转换

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="@*|node()|/">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()">
            <xsl:sort select="@kname"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>
<xsl:template match="text()">
    <xsl:value-of select="normalize-space(text())"/>
</xsl:template>

我会把它保存到一个文件中,如果从命令行运行

xsltproc normalize-space.xsl file.xml

或在管道中

run_some_command | xsltproc normalize-space.xsl - | xmllint --format -

xmllint --noblanks 并没有将我想要的所有空格字符都描述为“可忽略”。这在技术上几乎可以肯定是正确的,但不是我想要的。

于 2018-11-09T00:23:37.370 回答