Nokogiri搜索单词内容控件

时间:2014-12-22 17:32:25

标签: ruby xml ms-word nokogiri

我想在document.xml中找到所有Microsoft Word内容控制节点。因为我要预处理这些控件,我需要从给定的xml节点递归地找到这些人,但我想在第一次出现时停止。

示例数据:(内容控制节点是<w:sdt>

假设这些是我可以从节点X看到的节点:

<w:tc>
  <w:tcPr>
  ...
  </w:tcPr>
  <!-- A content control node I want to get -->
  <w:sdt>
    <w:sdtPr>
    ...
    </w:sdtPr>
    <w:sdtEndPr/>
    <w:sdtContent>
      ...
      <!--- Embedded in a content control. I don't want it now --->
      <w:sdt> 
        ...
      </w:sdt>
    </w:sdtContent>
  </w:sdt>
  ...
  <!-- Another content control ! It isn't embedded in a <w:sdt>, so I want this one -->
  <w:sdt>
  </w:sdt>
</w:tc>
...
<!--- Another one ! Not at the same depth, but not embedded so I want it ! -->
<w:sdt>
...
</w:sdt>

我想要上面给出的4个节点中的3个。如果我只做一个nodeX.search('.//sdt'),我会抓住所有4个吧?如何排除嵌入的?

1 个答案:

答案 0 :(得分:0)

只需考虑所有sdt节点并继续查看其父节点

  • 您找到节点X,这意味着内容控件未被嵌入(保留此节点)
  • 您找到sdt祖先

代码:

def find_nested_content_controls(node_set, cc_parent)
    nested_ccs = Nokogiri::XML::NodeSet.new(cc_parent.document)
    node_set.search('w|sdt').each do |cc|
        # Look at the parent node till we hit either the cc_parent, or another content_control
        current_node = cc
        loop do
            if current_node.parent == cc_parent 
                # It's not 2-level nested !
                nested_ccs.push(cc)
                break
            elsif /^sdt$/.match(current_node.parent.name)
                # It's >= 2-level nested, discard
                break
            elsif current_node == cc_parent.document.root
                raise 'Exception'
            end
            current_node = current_node.parent
        end
    end
    nested_ccs
end

注意:可以使用document.root作为两个参数进行调用,以查找整个文档中的第一级内容控件