试图找出最好的方法(使用我在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>
Run Code Online (Sandbox Code Playgroud)
XML文件包含我以这种格式重新连接的每篇KB文章.我很乐意用bash来解决它,我只是不知道如何根据搜索将它分成多个文件.
干杯,
粘土
如果您的文件是有效的XML,则可以使用xgrep或XMLStarlet等实用程序来解析文件以获取XPath表达式.例如,使用xgrep:
xgrep -x "//article[@id]" /tmp/foo
Run Code Online (Sandbox Code Playgroud)
这可能就是您所需要的.但是,它不会分开文章; 它比使用正则表达式更可靠地提取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'
Run Code Online (Sandbox Code Playgroud)
显然,您可以使用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
Run Code Online (Sandbox Code Playgroud)