3

我想遍历 XML 文件中的所有<HeadA><HeadB>元素,并为每个元素添加一个唯一的 id。到目前为止我尝试过的方法是:

@xml.each_element('//HeadA | //HeadB') do |heading|
  #add a new id
end

问题是,来自 XPath 的节点集//HeadA | //HeadB是所有HeadAs 后跟所有HeadBs。我需要的是所有HeadAs 和HeadBs 的有序列表,它们按照它们在文档中出现的顺序排列。

澄清一下,我的 XML 可能如下所示:

<Doc>
  <HeadA>First HeadA</HeadA>
  <HeadB>First HeadB</HeadB>
  <HeadA>Second HeadA</HeadA>
  <HeadB>Second HeadB</HeadB>
</Doc>

我从 XPath 得到的是:

  <HeadA>First HeadA</HeadA>
  <HeadA>Second HeadA</HeadA>
  <HeadB>First HeadB</HeadB>
  <HeadB>Second HeadB</HeadB>

当我需要得到的是按顺序排列的节点时:

  <HeadA>First HeadA</HeadA>
  <HeadB>First HeadB</HeadB>
  <HeadA>Second HeadA</HeadA>
  <HeadB>Second HeadB</HeadB>

所以我可以按顺序添加 ID。

4

4 回答 4

1

好的,第二次尝试,但我想我这次成功了:P

@xml.each_element('//*[self::HeadA or self::HeadB]') do |heading|
  puts heading.text
end
于 2010-11-15T14:38:08.643 回答
1

使用 Nokogiri 解析 XML:

xml = %q{
<Doc>
    <HeadA>First HeadA</HeadA>
    <HeadB>First HeadB</HeadB>
    <HeadA>Second HeadA</HeadA>
    <HeadB>Second HeadB</HeadB>
</Doc>
}

doc = Nokogiri::XML(xml)
doc.search('//HeadA | //HeadB').map{ |n| n.inner_text } #=> ["First HeadA", "First HeadB", "Second HeadA", "Second HeadB"]

对于您的任务,您可以替换mapeachoreach_with_index并且几乎完成。只需添加代码以插入唯一 ID。

于 2010-11-15T15:33:30.027 回答
0

如果您循环遍历所有 HeadA 并在每个 HeadA 内循环遍历每个 HeadB,它对您有用吗?

@xml.each_element("//HeadA") do |headA|
  #do stuff to headA
  headA.each_element("HeadB") do |headB|
    #do stuff to headB
  end
end
于 2010-11-15T13:57:22.687 回答
0

我想出了一个快速而肮脏的解决方案:

as_string = @xml.to_s
counter = 0
as_string.gsub!(/(<HeadA>|<HeadB>)/) do |str|
  result = str.sub '>', " id='#{counter}'>"
  counter += 1
  result
end
@xml = REXML::Document.new as_string

它可能不是最漂亮或最有效的,但它完成了我想要它做的事情。

编辑:接受 DD-Doug 的建议,我现在得到了这个:

counter = 0
@xml.each_element('//[self::HeadA or self::HeadB]') do |heading|
  heading.attributes['id'] = "id%03d" % counter
  counter += 1
end

哪个更好。

于 2010-11-15T14:14:29.260 回答