【问题标题】:REXML parsing an XML in rubyREXML 在 ruby​​ 中解析 XML
【发布时间】:2012-02-13 21:05:17
【问题描述】:

伙计们,

我将 REXML 用于示例 XML 文件:

<Accounts title="This is the test title">  
    <Account name="frenchcustomer">  
            <username name = "frencu"/>  
            <password pw = "hello34"/>  
            <accountdn dn = "https://frenchcu.com/"/>  
            <exporttest name="basic">  
                    <exportname name = "basicexport"/>  
                    <exportterm term = "oldschool"/>  
            </exporttest>  
    </Account>  
    <Account name="britishcustomer">  
            <username name = "britishcu"/>  
            <password pw = "mellow34"/>  
            <accountdn dn = "https://britishcu.com/"/>  
            <exporttest name="existingsearch">  
                    <exportname name = "largexpo"/>  
                    <exportterm term = "greatschool"/>  
            </exporttest>  
    </Account>  
</Accounts>

我正在阅读这样的 XML:

@data = (REXML::Document.new file).root
@dataarr = @@testdata.elements.to_a("//Account")

现在我想获取 frenchcustomer 的用户名,所以我尝试了这个:

@dataarr[@name=fenchcustomer].elements["username"].attributes["name"]

这个失败,我不想使用数组索引,例如

@dataarr[1].elements["username"].attributes["name"]

会起作用,但我不想这样做,我在这里缺少什么吗?我想使用数组并使用帐户名称获取法国用户的用户名。

非常感谢。

【问题讨论】:

  • 我已经更新了我的答案,所以有一个示例可以在不指定索引的情况下获取名为“frenchcustomer”的元素

标签: ruby rexml


【解决方案1】:

我建议你使用XPath

对于第一个匹配,你可以使用first方法,对于一个数组,只需使用match

上面的代码返回帐户“frenchcustomer”的用户名:

REXML::XPath.first(yourREXMLDocument, "//Account[@name='frenchcustomer']/username/@name").value

如果你真的想使用@@testdata.elements.to_a("//Account")创建的数组,你可以使用find方法:

french_cust_elt = the_array.find { |elt| elt.attributes['name'].eql?('frenchcustomer') }
french_username = french_cust_elt.elements["username"].attributes["name"]

【讨论】:

    【解决方案2】:
    puts @data.elements["//Account[@name='frenchcustomer']"]
          .elements["username"]
          .attributes["name"]
    

    如果你想遍历多个相同的名字:

    @data.elements.each("//Account[@name='frenchcustomer']") do |fc|
      puts fc.elements["username"].attributes["name"]
    end
    

    【讨论】:

      【解决方案3】:

      我不知道你的@@testdata是什么,我用下面的测试代码试过:

      require "rexml/document"
      
      @data = (REXML::Document.new DATA).root 
      @dataarr = @data.elements.to_a("//Account")
      
      # Works
      p @dataarr[1].elements["username"].attributes["name"]
      
      #Works not
      #~ p @dataarr[@name='fenchcustomer'].elements["username"].attributes["name"]
      
      #@dataarr is an array
      @dataarr.each{|acc|
        next unless acc.attributes['name'] =='frenchcustomer'
        p acc.elements["username"].attributes["name"]
      }
      
      #@dataarr is an array
      puts "===Array#each"
      @dataarr.each{|acc|
        next unless acc.attributes['name'] =='frenchcustomer'
        p acc.elements["username"].attributes["name"]
      }
      
      puts "===XPATH"
      @data.elements.to_a("//Account[@name='frenchcustomer']").each{|acc|
        p acc.elements["username"].attributes["name"]
      }
      
      __END__
      <Accounts title="This is the test title">
       <Account name="frenchcustomer">
       <username name = "frencu"/>
       <password pw = "hello34"/>
       <accountdn dn = "https://frenchcu.com/"/>
       <exporttest name="basic">
       <exportname name = "basicexport"/>
       <exportterm term = "oldschool"/>
       </exporttest>
       </Account>
       <Account name="britishcustomer">
       <username name = "britishcu"/>
       <password pw = "mellow34"/>
       <accountdn dn = "https://britishcu.com/"/>
       <exporttest name="existingsearch">
       <exportname name = "largexpo"/>
       <exportterm term = "greatschool"/>
       </exporttest>
       </Account>
       </Accounts>
      

      我对rexml不是很熟悉,所以希望有更好的解决方案。但也许有人可以使用我的代码来构建更好的解决方案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-10
        • 2014-05-16
        • 2021-01-20
        相关资源
        最近更新 更多