尝试找出最好的方法(使用我在Grep / Sed / Awk中所知的方法)根据它的单个字符串(键?)分割XML文件。我有一个XML文件,它是我所有当前FAQ条目的SQL转储,因此它包含一个条目ID,然后是一个相当大的HTML格式文档。我希望将这些条目分开,以便我可以轻松地将它们弹出到编辑器中并清理格式以导入到新的KB / FAQ系统。以下是我的数据示例:
<article id="3">
<language>en</language>
<category>Category Name</category>
<keywords>Keywords, by, comma</keywords>
<question>Question?</question>
<answer>HTML Formatting</answer>
<author>Author</author>
<data>2010-05-13 09:32</data>
</article>
XML文件包含我以这种格式重新连接的每篇KB文章。我很乐意用bash来搞清楚,我只是不知道如何根据搜索将它分成多个文件。
干杯,
粘土
答案 0 :(得分:6)
如果您的文件是有效的XML,则可以使用xgrep或XMLStarlet之类的实用程序来解析文件以获取XPath表达式。例如,使用xgrep:
xgrep -x "//article[@id]" /tmp/foo
这可能就是您所需要的。然而,它不会分裂文章;它比使用正则表达式更可靠地提取XML的正确部分。
如果您确实需要将文章拆分为单独的文件,则可以执行以下操作:
xgrep -x "//article[@id]" /tmp/foo.rb |
ruby -ne 'BEGIN { counter=0 }
counter += 1 if /<article/
if /<article/ ... /<\/article/
File.open("#{counter}.xml", "a") { |f| f.puts $_ }
end'
显然,您可以使用Ruby XML库完成所有工作,但我更喜欢将此类问题视为shell管道。您的里程可能会有所不同。
另外,请注意上面的Ruby脚本将按顺序编号您的文章而不是文章ID。如果您的XML中有重复的ID,则可能更好。
好的,好的......我不能单独留下这个。首先在上面的管道中使用外部shell实用程序似乎是一个好主意,但如果您还是要使用Perl或Ruby,那么您也可以使用XmlSimple库。
下面的Ruby脚本比管道版本稍长,但为您提供了更多的控制和灵活性。以此为出发点,考虑您的所有可能性:
#!/usr/bin/env ruby
require 'xmlsimple'
counter = 0
node_name = 'article'
xml = XmlSimple.xml_in '/tmp/foo'
xml[node_name].uniq.each do |node|
counter = sprintf("%03d", counter.next)
XmlSimple.xml_out(node,
RootName: node_name,
OutputFile: "/tmp/#{counter}.xml")
end
答案 1 :(得分:2)
cat file.xml | \
perl -p -i -e 'open(F, ">", ($1).".xml") if /<article id="(\d+)"/; print F;'
将根据文章的ID分割xml文件。每个文章部分都将存储在自己的文件中,其ID号在名称中。
即使对于hige文件(sed
,awk
等,它的工作速度也非常快,在这种情况下解决方案真的很慢。)
答案 2 :(得分:0)
这是awk的一个简单想法:
每当您点击带有文章开始标记的行时,将计数器变量递增1。然后,为每一行进行系统调用,如“echo $ 0&gt;&gt; file $ COUNTER”。这应该很容易实现