使用Nokogiri和变量中的上祖先节点选择多个节点

Dan*_* S. 5 css ruby variables nokogiri nodes

最后几天,我正在寻找任何解决方案,使用Nokogiri获取多个节点,并在祖先节点中使用参考变量.

我需要的是:实际上我正在收集"Segment"节点的所有"Id".然后我想用"Segment"节点收集所有后续"资源".为了收集"资源",我想将"Id"设置为变量.

<CPL>
  <SegmL>
    <Segment>
        <Id>UUID</Id> #UUID as a variable
        <Name>name_01</Name>
        <SeqL>
            <ImageSequence>
                <Id>UUID</Id>
                <Track>UUID</Track>
                    <ResourceList>
                        <Resource> #depending on SegmentId
                            <A>aaa</A>
                            <B>bbb</B>
                            <C>ccc</C>
                            <D>ddd</D>
                        </Resource>
                    </ResourceList>
            </ImageSequence>
            <AudioSequence>
                <Id>UUID</Id>
                <Track>UUID</Track>
                    <ResourceList>
                        <Resource>
                            <A>aaa</A>
                            <B>bbb</B>
                            <C>ccc</C>
                            <D>ddd</D>
                        </Resource>
                    </ResourceList>
            </AudioSequence>
        </SequL>
    </Segment>
    <Segment>
        <Id>UUIDa</Id>
        <Name>name_02</Name>
        <SequL>
            <ImageSequence>
                <Id>UUID</Id>
                <Track>UUID</Track>
                    <ResourceList>
                        <Resource>
                            <A>aaa</A>
                            <B>bbb</B>
                            <C>ccc</C>
                            <D>ddd</D>
                        </Resource>
                    </ResourceList>
            </ImageSequence>
            <AudioSequence>
                <Id>UUID</Id>
                <Track>UUID</Track>
                    <ResourceList>
                        <Resource>
                            <A>aaa</A>
                            <B>bbb</B>
                            <C>ccc</C>
                            <D>ddd</D>
                        </Resource>
                    </ResourceList>
            </AudioSequence>
        </SequL>
    </Segment>
  </SegmL>
</CPL>
Run Code Online (Sandbox Code Playgroud)

每个收集的所有资源数据 A = Resource.css("A").text.gsub(/\n/,"")

#first each do
cpls.each_with_index do |(cpl_uuid, mycpl), index|
cpl_filename = mycpl
cpl_file = File.open("#{resource_uri}/#{cpl_filename}")
cpl = Nokogiri::XML( cpl_file ).remove_namespaces!

#get UUID for UUID checks
cpl_uuid = cpl.css("Id").first.text.gsub(/\n/,"")
cpl_root_edit_rate  = cpl.css("EditRate").first.text.gsub(/\s+/, "\/")

  #second each do   
  cpl.css("Segment").each do |s| # loop segment
      cpl_segment_list_uuid = s.css("Id").first.text.gsub(/\n/,"") #uuid of segment list

      #third each do
      cpl.css("Resource").each do |f| #loop resources
          cpl_A = f.css("A").text.gsub(/\n/,"") # uuid of A
          cpl_B = f.css("B").text.gsub(/\n/,"") # uuid of B
      end #third
  end #second
end #first
Run Code Online (Sandbox Code Playgroud)

我的表达式给了我存储在数组中的这些信息:

A = 48000.0 
B = 240000.0 
C = 0.0 
D = 240000.0 

Some functions to calculate an average on the resources.

puts all_arry 

A = 5.0
B = 5.0
C = 5.0
D = 5.0
A = 5.0
B = 5.0
C = 5.0
D = 5.0


=8 values -> only 4 values existing for the exact loop (2 average values per Segment)
Run Code Online (Sandbox Code Playgroud)

目前所有"SegmentId"都在收集所有"资源"

如何将每个Segment Id的后续资源准确地分配为变量?

我曾经使用过这段代码,但是循环是空的,因为有更多的节点在"段"的"Id"和每个"资源""A","B"......之间.

if cpl.at("Segment/Id:contains(\"#{cpl_segment_list_uuid}\")")
   cpl.css("Resource").each do |f|
      #collecting resources here for each segmet
   end
end
Run Code Online (Sandbox Code Playgroud)

所有节点都没有属性,ID,类等.

愿你能解决我的问题.首先,我将在政治上感谢你的支持!

更新10/07/16

我还使用以下表达式为资源上的"each do"运行代码:

expression = "/SegmetList/Segment[Id>cpl_segment_list_uuid]"
cpl.xpath(expression).each do |f|
Run Code Online (Sandbox Code Playgroud)

它运行"each do",但我没有得到内部节点

cpl.css("Segment:contains(\"#{cpl_segment_list_uuid}\") > Resource").each do |f|
Run Code Online (Sandbox Code Playgroud)

与以前相同

并且使用"if"条件,也是同样的问题:

if cpl.at("Segment/Id:contains(\"#{cpl_segment_list_uuid}\")").each do|f|
#some code
end
Run Code Online (Sandbox Code Playgroud)

更新2016/18/10

实际上我得到了正确数量的资源(4),但每个细分仍然没有分开.因此每个细分中有四个相同的资源.

为什么我没有获得所有资源的双倍数,是我在"Segment"-loop中创建数组.

这是目前的代码:

#first each do
cpls.each_with_index do |(cpl_uuid, mycpl), index|
cpl_filename = mycpl
cpl_file = File.open("#{resource_uri}/#{cpl_filename}")
cpl = Nokogiri::XML( cpl_file ).remove_namespaces!

#get UUID for UUID checks
cpl_uuid = cpl.css("Id").first.text.gsub(/\n/,"")
cpl_root_edit_rate  = cpl.css("EditRate").first.text.gsub(/\s+/, "\/")

  #second each do   
  cpl.css("Segment").each do |s| # loop segment
      cpl_segment_list_uuid = s.css("Id").first.text.gsub(/\n/,"") #uuid of segment list
      array_for_resource_data = Array.new

      #third each do
      s.css("Resource").each do |f| #loop resources #all resources
      s.search('//A | //B').each do |f| #selecting only resources "A" and "B"
          cpl_A = f.css("A").text.gsub(/\n/,"") # uuid of A
          cpl_B = f.css("B").text.gsub(/\n/,"") # uuid of B
      end #third
  end #second
end #first
Run Code Online (Sandbox Code Playgroud)

我希望我的更新能为您提供更多详细信息.非常感谢您的帮助和回答!

更新2016/31/10

段的双倍输出的问题是固定的.现在我在段下的每个序列上还有一个循环:

cpl.css("Segment").each do |u|
  segment_list_uuid = u.css("Id").first.text.gsub(/\n/,"")
  sequence_list_uuid_arr = Array.new

    u.xpath("//SequenceList[//*[starts-with(name(),'Sequence')]]").each do |s|
      sequence_list_uuid = s.css("TrackId").first.text#.gsub(/\n/,"") 
      sequence_list_uuid_arr.push(cpl_sequence_list_uuid)

    #following some resource nodes
    s.css("Resource").each do |f|
      asset_uuid = f.css("TrackFileId").text.gsub(/\n/,"") 
      resource_uuid = f.css("Id").text.gsub(/\n/,"") 
      edit_rate = f.css("EditRate").text.gsub(/\s+/, "\/")
      #some more code
    end #resource
  end #sequence list
end #segment
Run Code Online (Sandbox Code Playgroud)

现在我希望在每个独特序列下获得所有不同的"资源".我必须列出所有不同的资源,并总结一些收集的值.

有没有办法在相同的"序列ID"下收集具有不同值(子节点)的每个资源?目前,我不知道任何解决方案....所以没有代码我可以告诉你,这将部分工作.

"资源"循环的each_with_index不起作用.

愿你有一些想法或任何方法来帮助我解决我的新问题吗?

aku*_*uhn 0

尝试

resource.search('.//A | .//B')
Run Code Online (Sandbox Code Playgroud)

.//将 xpath 查询锚定在当前元素,而不是搜索整个文档。

例子

elem = doc.search('ImageSequence').first
elem.search('//A') # returns all A in the whole document
elem.search('.//A') # returns all A inside element
Run Code Online (Sandbox Code Playgroud)