XML-对元素进行分组和合并,同时保留所有元素文本

XML-对元素进行分组和合并,同时保留所有元素文本,xml,bash,macos,xmlstarlet,xmllint,Xml,Bash,Macos,Xmlstarlet,Xmllint,我有一些XML,其中有不同文本的重复元素。重复的元素既连续又不连续。我正在尝试合并这些元素中的文本,并删除重复的元素。选择的工具是xmlstarlet(在osx上的bash中) 输入: 乐趣 福 酒吧 时代 期望输出: 富吧 欢乐时光 我要做的是使用XSLT进行转换 然后可以使用按名称对元素进行分组 例如 XML输入(test.XML;根据评论中的问题编辑) XML输出 <wrapper> <data> <item_a>foo bar&

我有一些XML,其中有不同文本的重复元素。重复的元素既连续又不连续。我正在尝试合并这些元素中的文本,并删除重复的元素。选择的工具是
xmlstarlet
(在
osx
上的
bash
中)

输入:


乐趣
福
酒吧
时代
期望输出:


富吧
欢乐时光

我要做的是使用XSLT进行转换

然后可以使用按名称对元素进行分组

例如

XML输入(test.XML;根据评论中的问题编辑)

XML输出

<wrapper>
   <data>
      <item_a>foo bar</item_a>
      <item_b>fun times</item_b>
   </data>
   <data>
      <item_a>Uh oh should be in own element</item_a>
   </data>
</wrapper>

富吧
欢乐时光
哦,应该是自己的元素

Daniel的XSLT解决方案将是最好的解决方案。然而,我喜欢让编程语言为我关心XML的细节。Ruby非常适合处理XML:

gem install xml-simple

ruby -e '
    require "xmlsimple"
    data = XmlSimple.xml_in(ARGV.shift, {"keeproot" => true})
    items = data["wrapper"][0]["data"][0]
    items.each_key {|n| items[n] = [ items[n].join(" ") ]}
    out = XmlSimple.xml_out(data, {"keeproot" => true})
    puts out
' file.xml

感谢@CarlosCavero-在我的搜索中,我没有看到这个问题在任何其他问题中得到明确的解决。我希望我给出的输入/输出示例很清楚—是否需要改进?@tesolat—欢迎使用堆栈溢出。我同意;好的第一个问题+1。唯一能让事情变得更好的是,如果你展示了你所尝试过的;即使它不接近你想要的输出。有总比没有好。:-)谢谢起初,我确实有一个(糟糕的)计划,使用
perl
slurp模式跨行正则表达式并处理它,但后来我想到了一个
xslt
解决方案,但不知道从哪里开始。谢谢你的帮助,不客气。你是对的;XSLT是比正则表达式好得多的选项。:-)如果你遇到;“xmlstarlet:command not found”(您确实安装了xmlstarlet),然后将命令行改为
xml tr test.xsl test.xml
——注意
xml
而不是
xmlstarlet
,谢谢Daniel——我不知道Muenchian分组,这是一个很大的帮助。在您的解决方案中,如果我添加了两行(
bad
times
),它们也将被分组和合并。您如何明确控制模板作用于哪些元素?@tesolat-您将如何处理它,这取决于是否有更多的元素需要忽略,还是有更多的元素需要具体处理。在您的示例中,只有一个元素可以忽略,因此我只需在for each中向
*
添加一个谓词来忽略这些元素。我将更新我的答案中的示例。@tesolat-如果您想换一种方式并指定要处理的元素,您可以将
*[not(self::ignore)]
更改为
(item|a | item|b)
。(Fiddle:)@tesolat-我的更新是否足够,或者您是否仍有问题?如果足够,请点击旁边的复选标记接受我的答案。谢谢。谢谢@glenn jackman。我不会接受这个答案,因为我被限制在
xmlstartet
中,但是在线程中记录第二种方法非常好。我相信其他人会从中受益!
xmlstarlet tr test.xsl test.xml
<wrapper>
   <data>
      <item_a>foo bar</item_a>
      <item_b>fun times</item_b>
   </data>
   <data>
      <item_a>Uh oh should be in own element</item_a>
   </data>
</wrapper>
gem install xml-simple

ruby -e '
    require "xmlsimple"
    data = XmlSimple.xml_in(ARGV.shift, {"keeproot" => true})
    items = data["wrapper"][0]["data"][0]
    items.each_key {|n| items[n] = [ items[n].join(" ") ]}
    out = XmlSimple.xml_out(data, {"keeproot" => true})
    puts out
' file.xml
<wrapper>
  <data>
    <item_b>fun times</item_b>
    <item_a>foo bar</item_a>
  </data>
</wrapper>
    items.select! {|name, value| name.start_with? "item"}