INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Jobs

Read XML file with Nokogiri

Read XML file with Nokogiri

(OP)
Hi

This has been bugging me all day...
I'm a Ruby newbie and I need some help..
I'm trying to read an XML file to retrieve 2 values.

Below is an example of the xml.

<?xml version="1.0" encoding="utf-16"?>
<resources applicationName="Testapp" author="Joe Bloggs">
  <resource type="assembly" name="reader.dll" version="1.0.0.1"/>  
  <resource type="sql" name="script.sql" version="1.0.0.0"/>
  <resource type="file" name="text.txt" version="2.0.0.3"/>
  <resource type="assembly" name="writer.dll" version="1.12.0.765"/>
</resources>

I want to retrieve the "name" and "version" for each "resource" that is of type="assembly" using Nokogiri.

I need to use Nokogiri as it is able to read UTF16 files and can handle & etc...

Can someone help me please?  I don't have the code to hand that I wrote today, but can update this request tomorrow with my attempts so far.

I find the XML thing hard.

My Ruby version is 1.9.1 P429

Thanks in advance.

RE: Read XML file with Nokogiri

(OP)
As promised here is the code I wrote so far;

filename = Test.xml'
     file_content = File.read(filename)
     xmldoc = Nokogiri::XML(file_content)
     puts "Root attribute : " + xmldoc.root.attributes["applicationName"]


     puts "Type : " + xmldoc.elements.elements[1].attributes["resource/type"]

I can get the "applicationName" attribute, but cannot bring back  the "type" attribute.

RE: Read XML file with Nokogiri

Hi

Like this ?

CODE --> Ruby

require 'nokogiri'
xml=Nokogiri::XML File.open 'fairyliquid.xml'
xml.xpath('//resource').each { |node| puts " - #{ node['name'] } ( #{ node['version'] } )" }

CODE --> output

 - reader.dll ( 1.0.0.1 )
 - script.sql ( 1.0.0.0 )
 - text.txt ( 2.0.0.3 )
 - writer.dll ( 1.12.0.765 )

Quote (fairyliquid):

I need to use Nokogiri as it is able to read UTF16 files and can handle & etc...
Well, I had problem with the encoding, so I had to change it to UTF-8 in the sample file to work. Regarding the ampersand ( & ) and generally any character entities, every XML library should treat them the same way.
 

Feherke.
http://free.rootshell.be/~feherke/

RE: Read XML file with Nokogiri

(OP)
Thanks for your quick response!

The XML sample I gave does work with your code, however I missed out a node.  The xml to parse should look like this:

<?xml version="1.0" encoding="utf-16"?>
<resourcespec applicationName="Testapp" author="Joe Bloggs">
    <resources>
        <resource type="assembly" name="reader.dll" version="1.0.0.1"/>
        <resource type="sql" name="script.sql" version="1.0.0.0"/>
        <resource type="file" name="text.txt" version="2.0.0.3"/>
        <resource type="assembly" name="writer.dll" version="1.12.0.765"/>
    </resources>
</resourcespec>

So taking your code I  tried to extend it to cover the new node.  I still want the same values but keep getting an error - "Can't convert nil into String"

  xmldoc.xpath('//resourcespec/resources/resource').each { |node| puts " - #{ node['type'] } ( #{ node['name'] } )" }

Also, within the above line how do you insert a case statement?  I want to see if the "type" is an "assembly" to get the "name".  
This is probably really basic stuff, but I'm struggling with the formatting of the code and the countlesss {} []s.

If it was .Net I'd be fine.

Thanks
      

RE: Read XML file with Nokogiri

(OP)
It's ok I sorted it out.

Just placed the do and end in the right place.  So now it's full steam ahead.  Thanks again! :)

 xmldoc.xpath('//resourcespec/resources/resource').each do |node| puts " - #{ node['type'] } ( #{ node['name'] } )"
end

RE: Read XML file with Nokogiri

Hi

Quote (fairyliquid):

The XML sample I gave does work with your code, however I missed out a node. (...) So taking your code I  tried to extend it to cover the new node.
No need to change anything. In XPath "//" means anywhere in the structure. So unless you want to exclude resource nodes found somewhere else, ( not children of a resources node, ) you have to modify nothing. Anyway, your modified code works for me.

Quote (fairyliquid):

Also, within the above line how do you insert a case statement? I want to see if the "type" is an "assembly" to get the "name".
So far that sounds like a simple if. That can be filtered out in XPath :

CODE

xml.xpath('//resource[@type="assembly"]').each { |node| puts " - #{ node['name'] } ( #{ node['version'] } )" }
But of course, an if in the Ruby code can also do it :

CODE

xml.xpath('//resource').each { |node| puts " - #{ node['name'] } ( #{ node['version'] } ) #{ node['type'] }" if node['type']=='assembly' }
If you change the code block's syntax will be simpler to see where to add more code :

CODE

xml.xpath('//resource').each do |node|
  if node['type']=='assembly'
    puts " - #{ node['name'] } ( #{ node['version'] } ) #{ node['type'] }"
  end
end
Then changing to case is a snap :

CODE

xml.xpath('//resource').each do |node|
  case node['type']
    when 'assembly'
      puts " - #{ node['name'] } ( #{ node['version'] } ) #{ node['type'] }"
    when 'sql'
      puts ' - Handling sql resources is on TODO list'
    else
      puts " - Unhandled resource type : #{ node['type'] }"
  end
end

Feherke.
http://free.rootshell.be/~feherke/

RE: Read XML file with Nokogiri

(OP)
My issue is not resolved :(

I omitted to say I have a namespace which has been generated by BizTalk.  The sample xml file did not show this as I didn't think it would be an issue.

If the namespace is removed from the file parsing works correctly.

So my next question is how do you remove the offending namespace?

The namespace offender is:
xmlns="http://schemas.microsoft.com/BizTalk/ApplicationDeployment/ResourceSpec/2004/12"

FYI the xml is now:

<?xml version="1.0" encoding="utf-16"?>
<resourcespec xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ApplicationName="Mercury.Syndication2" xmlns="http://schemas.microsoft.com/BizTalk/ApplicationDeployment/ResourceSpec/2004/12" applicationName="Testapp" author="Joe Bloggs">
    <resources>
        <resource type="assembly" name="reader.dll" version="1.0.0.1"/>
        <resource type="sql" name="script.sql" version="1.0.0.0"/>
        <resource type="file" name="text.txt" version="2.0.0.3"/>
        <resource type="assembly" name="writer.dll" version="1.12.0.765"/>
    </resources>
</resourcespec>



 

RE: Read XML file with Nokogiri

Hi

CODE

xml.xpath('//biz:resource','biz'=>'http://schemas.microsoft.com/BizTalk/ApplicationDeployment/ResourceSpec/2004/12').each { |node| puts " - #{ node['name'] } ( #{ node['version'] } )" }

Feherke.
http://free.rootshell.be/~feherke/

RE: Read XML file with Nokogiri

(OP)
Yeeehhaaaaaa!!!

Thank you for your speedy replies.  
This is definitely the fix.
I'll now about the namespace thing in future.  
Simple but clever!
:)

 

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!

Resources

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close