icn
icn

Reputation: 17876

Search node in xml by using Nokogiri xpath (with xml namesapce)

I found Nokogiri is quite powerful on dealing with xml but I met a special case

I am trying to search a node in xml file like this

     <?xml version="1.0" encoding="utf-8" ?>
     <ConfigurationSection>
      <Configuration xmlns="clr-namespace:Newproject.Framework.Server.Store.Configuration;assembly=Newproject.Framework.Server" >
       <Configuration.Store>SqlServer</Configuration.Store>
       <Configuration.Engine>Staging</Configuration.Engine>
      </Configuration>
   </ConfigurationSection>

When I do a

xml = File.new(webconfig,"r")
doc = Nokogiri::XML(xml.read)
nodes = doc.search("//Configuration.Store")
xml.close

I got empty nodes. Something am I missing? I have tried

 nodes = doc.search("//Configuration\.Store")

still no luck.

Updated: I have attached the whole xml file

Updated the xml Again: My mistake, it does have a namaspace

Upvotes: 4

Views: 2973

Answers (2)

ezkl
ezkl

Reputation: 3851

EDIT #2: Solution now includes #parse_with_namespace

You can find a number of Nokogiri methods pertaining to namespaces in the Nokogiri::XML::Node documentation.

# encoding: UTF-8
require 'rspec'
require 'nokogiri'

XML = <<XML
<?xml version="1.0" encoding="utf-8" ?>
  <ConfigurationSection>
   <Configuration xmlns="clr-namespace:Newproject.Framework.Server.Store.Configuration;assembly=Newproject.Framework.Server" >
    <Configuration.Store>SqlServer</Configuration.Store>
    <Configuration.Engine>Staging</Configuration.Engine>
   </Configuration>
</ConfigurationSection>
XML


class ConfigParser
  def parse(xml)
    doc = Nokogiri::XML(xml).remove_namespaces!
    configuration = doc.at('/ConfigurationSection/Configuration')
    store   = configuration.at("./Configuration.Store").text
    engine  = configuration.at("./Configuration.Engine").text
    {store: store, engine: engine}
  end

  def parse_with_namespace(xml)
    doc = Nokogiri::XML(xml)
    configuration = doc.at('/ConfigurationSection/xmlns:Configuration', 'xmlns' => 'clr-namespace:Newproject.Framework.Server.Store.Configuration;assembly=Newproject.Framework.Server')
    store   = configuration.at("./xmlns:Configuration.Store", 'xmlns' => 'clr-namespace:Newproject.Framework.Server.Store.Configuration;assembly=Newproject.Framework.Server').text
    engine  = configuration.at("./xmlns:Configuration.Engine", 'xmlns' => 'clr-namespace:Newproject.Framework.Server.Store.Configuration;assembly=Newproject.Framework.Server').text
    {store: store, engine: engine}
  end
end

describe ConfigParser do
  before(:each) do
    @parsed         = subject.parse XML
    @parsed_with_ns = subject.parse_with_namespace XML
  end

  it "should be able to parse the Configuration Store" do
    @parsed[:store].should eq "SqlServer"
  end

  it "should be able to parse the Configuration Engine" do
    @parsed[:engine].should eq "Staging"
  end

  it "should be able to parse the Configuration Store with namespace" do
    @parsed_with_ns[:store].should eq "SqlServer"
  end

  it "should be able to parse the Configuration Engine with namespace" do
    @parsed_with_ns[:engine].should eq "Staging"
  end
end

Upvotes: 5

Phrogz
Phrogz

Reputation: 303198

require 'nokogiri'
XML = "<Configuration>
  <Configuration.Store>SqlServer</Configuration.Store>
  <Configuration.Engine>Staging</Configuration.Engine>
</Configuration>"
p Nokogiri::VERSION, Nokogiri.XML(XML).search('//Configuration.Store')
#=> "1.5.0"
#=> [#<Nokogiri::XML::Element:0x8103f0f8 name="Configuration.Store" children=[#<Nokogiri::XML::Text:0x81037524 "SqlServer">]>]

p RUBY_DESCRIPTION
#=> "ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-darwin10.7.0]"

Upvotes: 0

Related Questions