我的文件包含无法明确识别的数据。像这样说:
<?xml version="1.0" encoding="UTF-8" ?><ns0:collection
xmlns:ns0="http://namspace/Service/1.0"><Record>
.
.</Record></ns0:collection>
我必须将 N 个此类文件合并并创建一个文件。所以我需要完成以下工作:
- 我只需
</ns0:collection>
要从第一个文件中删除结束标签 - 删除接下来 (n-1) 个文件中的
<?xml version="1.0" encoding="UTF-8" ?><ns0:collection xmlns:ns0="http://namspace/Service/1.0">
和</ns0:collection>
- 必须仅删除
<?xml version="1.0" encoding="UTF-8" ?><ns0:collection xmlns:ns0="http://namspace/Service/1.0">
最后一个文件并将它们全部合并在一起
我尝试使用sed
命令处理第一个文件,但没有产生任何结果,“merged.xml”为空。
sed '/<\/ns0:collection>/d' $file1 > merged.xml
有什么建议么?
答案1
您没有指定只能使用sed
,因此如果您有权访问xml_grep
(请参阅从命令行合并多个 XML 文件,第二个答案),我建议这样做,因为它为您完成了很多繁重的工作,并且对于像这样的简单合并作业可以通过一个命令完成:
xml_grep --cond Record --wrap "ns0:collection" --descr 'xmlns:ns0="http://namespace/Service/1.0"' --encoding "UTF-8" *.xml
测试文件:
测试.xml
<?xml version="1.0" encoding="UTF-8" ?><ns0:collection
xmlns:ns0="http://namespace/Service/1.0""><Record>
Test
</Record></ns0:collection>
测试1.xml
<?xml version="1.0" encoding="UTF-8" ?><ns0:collection
xmlns:ns0="http://namespace/Service/1.0"><Record>
Test 1<a>a</a><b c="c">d</b>
</Record></ns0:collection>
结果
<?xml version="1.0" encoding="UTF-8" ?>
<ns0:collection xmlns:ns0="http://namespace/Service/1.0">
<Record>
Test 1<a>a</a><b c="c">d</b></Record><Record>
Test
</Record>
</ns0:collection>
在处理 XML 文件时,我更喜欢使用 XML 感知工具,因为搞乱结构的可能性sed
相当高,并且很容易得到格式错误的 XML 文档!
答案2
我建议使用 usingsed
不适合处理 XML,而应使用解析器。
我还建议您在这里遇到 XY 问题 - 这不是删除标签,而是合并 XML 文件。
就我个人而言 - 我喜欢perl
并且XML::Twig
:
#!/usr/bin/env perl
use strict;
use warnings;
#load the parser
use XML::Twig;
#get our file list - we use the "first" file as the basis.
#can use sort on this list if desired.
my ( $first_file, @other_files ) = glob ( 'C://tmp//xmltest/*.xml' );
#Our 'parent' document.
my $doc = XML::Twig -> new -> parsefile ( $first_file );
foreach my $file ( @other_files ) {
my $mergedoc = XML::Twig -> new -> parsefile ( $file );
#//Record means any <Record> node anywhere in the tree.
foreach my $record ( $mergedoc -> get_xpath ( '//Record' ) ) {
$record -> cut;
#paste it into our parent doc, as the last node.
$record -> paste ( after => $doc -> root -> last_child );
}
}
#set output formatting (optional)
$doc -> set_pretty_print ('indented_a');
#print to STDOUT.
$doc -> print;
#write to output file too
open ( my $output, '>', 'combined.xml' ) or die $!;
print {$output} $doc -> sprint;
close ( $output );
这会故意从目标 XML 中提取Record
元素,并在文档之间合并这些元素。然而,它是一种灵活的方法 -xpath
非常强大,并且是正则表达式的 XML 等价物 - 但效果更好,因为它具有上下文感知能力,而正则表达式则不然。
答案3
解决方案:
我需要从第一个文件中仅删除结束标记,解决方案:
sed -i.bak -e 's/<\/ns0:collection>/ /' -e 's/<\/Record>/ /' n0
删除接下来 (n-1) 个文件中的
<?xml version="1.0" encoding="UTF-8" ?><ns0:collection xmlns:ns0="http://namspace/Service/1.0">
和:</ns0:collection>
sed -i.bak -e 's/<?xml version=1.0 encoding=UTF-8 ?>.*<ns0:collection/ /' -e 's/xmlns.*/ /' -e 's/<\/R.*>.*>/ /' n1
对文件名范围执行此操作:
find . -type f -name "n[1-3]" -exec sed i.bak -e 's/<?xml version=1.0 encoding=UTF-8 ?>.*<ns0:collection/ /' -e 's/xmlns.*/ /' -e 's/<\/R.*>.*>/ /' {} \;
必须仅删除最后一个文件并将它们全部合并在一起:
sed i.bak -e 's/<?xml version=1.0 encoding=UTF-8 ?>.*<ns0:collection/ /' -e 's/xmlns.*/ /' ne
最后加入他们:
cat n0 n[1-3] ne > joined
我使用了以下文件:n0
、n1
、n2
、n3
和ne
。我在每个内容中添加了以下文本:
<?xml version="1.0" encoding="UTF-8" ?><ns0:collection
xmlns:ns0="http://namspace/Service/1.0"><Record>
hello from nigeria
</Record></ns0:collection>
生成的文件joined
如下所示:
<?xml version="1.0" encoding="UTF-8" ?><ns0:collection
xmlns:ns0="http://namspace/Service/1.0"><Record>
hello from nigeria
hello from nigeria
hello from nigeria
hello from nigeria
hello from nigeria
</Record></ns0:collection>
笔记:
我从第一个问题中看出,您
</Record></ns0:collection>
不仅需要删除两者,还需要删除</ns0:collection>
.所以我冒昧地这样做了,否则</Record>
当文件合并时我们会出现重复的条目。这里的文件名必须由您修改,以便您可以对所有文件运行一个命令,这里我使用了
n[1-3]
.选择最适合您的。请先运行测试并查看结果,这里我用的是
i.bak
sosed
自动创建备份。