REXML разбирает XML в ruby - PullRequest
1 голос
/ 14 февраля 2012

Народ,

Я использую 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")

Теперь я хочучтобы получить имя пользователя француза, поэтому я попробовал это:

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

это не удалось, я не хочу использовать индекс массива, например

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

будет работать, ноЯ не хочу этого делать, есть что-то, чего мне здесь не хватает.Я хочу использовать массив и получить имя пользователя француза, используя имя учетной записи.

Большое спасибо.

Ответы [ 3 ]

3 голосов
/ 14 февраля 2012

Я рекомендую вам использовать 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"]
1 голос
/ 14 февраля 2012
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
0 голосов
/ 14 февраля 2012

Я не знаю, каков ваш @@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, поэтому надеюсь, что есть лучшее решение. Но, возможно, кто-нибудь может взять мой код, чтобы построить лучшее решение.

...