从 xml 文件中删除标签

从 xml 文件中删除标签

我的文件包含无法明确识别的数据。像这样说:

<?xml version="1.0" encoding="UTF-8" ?><ns0:collection
xmlns:ns0="http://namspace/Service/1.0"><Record>
.
.</Record></ns0:collection>

我必须将 N 个此类文件合并并创建一个文件。所以我需要完成以下工作:

  1. 我只需</ns0:collection>要从第一个文件中删除结束标签
  2. 删除接下来 (n-1) 个文件中的<?xml version="1.0" encoding="UTF-8" ?><ns0:collection xmlns:ns0="http://namspace/Service/1.0"></ns0:collection>
  3. 必须仅删除<?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

解决方案:

  1. 我需要从第一个文件中仅删除结束标记,解决方案:

    sed -i.bak -e 's/<\/ns0:collection>/ /' -e 's/<\/Record>/ /' n0
    
  2. 删除接下来 (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.*>.*>/ /' {} \;
      
  3. 必须仅删除最后一个文件并将它们全部合并在一起:

    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

我使用了以下文件:n0n1n2n3ne。我在每个内容中添加了以下文本:

<?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>

笔记:

  1. 我从第一个问题中看出,您</Record></ns0:collection>不仅需要删除两者,还需要删除</ns0:collection>.所以我冒昧地这样做了,否则</Record>当文件合并时我们会出现重复的条目。

  2. 这里的文件名必须由您修改,以便您可以对所有文件运行一个命令,这里我使用了n[1-3].选择最适合您的。

  3. 请先运行测试并查看结果,这里我用的是i.baksosed自动创建备份。

相关内容