我有一个“类似XML”的文件,其中包含大量的配置数据。我说" XML - like“,因为它真的像3个XML文件连接在一起,用”]>分隔。“
例如。
<?xml version="1.0" encoding="UTF-8"?>
<hello><world>"Earth"</world></hello>]]>]]><?xml version="1.0" encoding="UTF-8"?>
<data><lemur><type>"Ring-tailed"</type></lemur></data>]]>]]><?xml version="1.0" encoding="UTF-8"?>
<data><lemur><type>"Mouse"</type></lemur></data>]]>]]>我正在编写一个脚本,它将调用xmllint来缩进文件中的所有XML标记。但是,xmllint (和许多其他xml格式化程序)似乎要求文件中只有一个XML文档。例如,文件需要以"<?xml version="1.0" encoding="UTF-8"?>“开头,并且只包含一个根树。
因此,我尝试编写一个awk脚本,将数据解析成不同的块,并将其传递给xmllint,但是我得到了一个无法通过的错误。我把脚本和输出放在下面。
$ awk '
BEGIN {
RS = "]]>]]>"
xmlFormatCommand = "xmllint --format -"
}
{
print $0 | xmlFormatCommand
}
' SmallTest.xml
-:3: parser error : XML declaration allowed only at the start of the document
<?xml version="1.0" encoding="UTF-8"?>
^
-:4: parser error : Extra content at the end of the document
<data><lemur><type>"Ring-tailed"</type></lemur></data>
^如果我在两个单独的操作中这样做,一个是awk打印到三个临时文件,另一个是xmllint对这些文件进行操作,那么它就能工作了。
例如。
awk 'BEGIN {RS = "]]>]]>"} {print $0 > "Section_" NR ".txt" }' SmallTest.xml这导致了三个文件Section_1.txt、Section_2.txt和Section_3.txt。Section_2.txt的内容如下:
$ cat Section_2.txt
<?xml version="1.0" encoding="UTF-8"?>
<data><lemur><type>"Ring-tailed"</type></lemur></data>我可以用xmllint格式化该文件:
$ cat Section_2.txt | xmllint --format -
<?xml version="1.0" encoding="UTF-8"?>
<data>
<lemur>
<type>"Ring-tailed"</type>
</lemur>
</data>所以,我不明白为什么我不能在awk脚本中首先将它输送到xmllint。
我很感激你能提供的任何帮助。
-Jon
发布于 2015-01-21 16:07:49
简单地说,你的问题是awk一直在使用相同的管道。管道是在打开时使用的完全相同的字符串(这意味着不能同时运行两次完全相同的命令)下记住的,记录将一个接一个地写入其中,因此只有一个xmllint进程将整个文件作为输入。
您可以通过在每次记录之后关闭管道来修复此问题:
$ awk '
BEGIN {
RS = "]]>]]>"
xmlFormatCommand = "xmllint --format -"
}
{
print $0 | xmlFormatCommand
close(xmlFormatCommand) # <-- HERE
}
' SmallTest.xml在这里,close接受用于记住管道的标识符(命令)作为参数。我知道,与其他编程语言相比,这看起来很奇怪。
由于您在问题的末尾将有一个空记录,顺便说一句,您可能需要在其中添加一个条件,以排除这些空记录。例如,
$ awk '
BEGIN {
RS = "]]>]]>"
xmlFormatCommand = "xmllint --format -"
}
! /^\s*$/ { # <-- HERE
print $0 | xmlFormatCommand
close(xmlFormatCommand)
}
' SmallTest.xml其中,/^\s*$/匹配在开头和结尾之间只有空格的记录,而!则反转该匹配。
发布于 2015-01-21 16:20:31
这是由于print命令的输出一直指向xmllint的同一个实例。
解决这一问题的最简单方法是使用xmllint创建输出文件:
awk '
BEGIN {
RS = "]]>]]>"
}
{
print $0 | "xmllint --format --output sample_"NR".xml -"
}
' SmallTest.xml如果这样做,您还会有一个错误,因为xmllint将在最后一行之后调用一次,而不留下任何输入-因此您可以只删除源xml中的最后一个分隔符,或者检查$0在awk脚本中是否有值。
若要将所有输出输出到stdout,请执行:
awk '
BEGIN {
RS = "]]>]]>"
}
{
print $0 | "xmllint --format -"
close("xmllint --format -")}
' SmallTest.xmlhttps://stackoverflow.com/questions/28071089
复制相似问题