Avoiding Nokogiri::XML::XPath::SyntaxError: ERROR: Undefined namespace prefix - ruby

I get the error "Nokogiri::XML::XPath::SyntaxError: ERROR: Undefined namespace prefix" when I do this:
doc.search('//text()[not(ancestor::w:delText]')
Based on this answer: How do I use xpath on nodes with a prefix but without a namespace?
*[name()="w:delText"]
can sort of solve the problem. But how do I do something similar like this to avoid the namespace error:
doc.search('//text()[not(ancestor::*[name()="w:delText"]')

I ended up solving the problem by editing the XML file and adding the namespaces in the root. Here is an example:
temp = Nokogiri::XML(#document_xml)
temp.root['xmlns:w'] = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
#doc = Nokogiri::XML(temp.to_xml(:save_with => Nokogiri::XML::Node::SaveOptions::AS_XML))

Related

Ignore namespaces on xmldocument in nokogiri

Im trying to learn to parse xml with nokogiri.
I dont have control of how the xml file is generated and it seems the namespaces are causing issues because they are not defined.
Im using the following test code to try to get this to work.
require 'nokogiri'
def getxml
xml_str = <<EOF
<root>
<THING1:things type="Container">
<PART1:Id type="Property">1234</PART1:Id>
<PART1:Name type="Property">The Name1</PART1:Name>
</THING1:things>
<THING2:things type="Container">
<PART2:Id type="Property">2234</PART2:Id>
<PART2:Name type="Property">The Name2</PART2:Name>
</THING2:things>
</root>
EOF
doc = Nokogiri::XML(xml_str)
puts(doc.errors())
doc.xpath('//Id').each do |thing|
puts(thing.inspect)
#puts "ID = " + thing.at_xpath('Id').content
#puts "Name = " + thing.at_xpath('Name').content
end
end
getxml()
I'm getting the following errors:
2:38: ERROR: Namespace prefix THING1 on things is not defined
3:34: ERROR: Namespace prefix PART1 on Id is not defined
4:36: ERROR: Namespace prefix PART1 on Name is not defined
6:38: ERROR: Namespace prefix THING2 on things is not defined
7:34: ERROR: Namespace prefix PART2 on Id is not defined
8:36: ERROR: Namespace prefix PART2 on Name is not defined
How am I suppose to deal with namespaces not defined. Is there a way to ignore namespaces.
Nokogiri does have the remove_namespaces! method, but it wont help in your case as your XML isn’t actually using namespaces.
As there are no namespace declarations, your XML elements are just treated as non-namespaced elements that contain a : character in their name. This makes it difficult to use with XPath as XPath assumes a : indicates a namespace.
One way to get round this is to use the local-name() function to select elements. For example to select all elements named PART1:Id you could use this:
doc.xpath('//*[local-name()="PART1:Id"]')
If you want to select all elements where the final part is Id, regardless of what the prefix is, such as PART1:Id and PART2:Id, you could combine local-name() with substring-after():
doc.xpath('//*[substring-after(local-name(), ":")="Id"]')

Ruby string interpolation not working when called from an included file

I have two files: urls.rb and testcase.rb. urls.rb has the following:
$event = "/sendmessage/#{id}"
The id in the url is generated in testcase.rb. This is the code in testcase.rb:
require 'urls.rb'
id = 100
puts $event
I am seeing the following error:
undefined local variable or method `id' for main:Object (NameError)
How do I resolve this error?
Local variables like id cannot be called across files. Their scopes are limited within a file. In order to use it, you have to assign id in the same file as it is used. Furthermore, your assignment of id after requiring 'urls.rb' is meaningless.
The problem is that you are attempting to use id in urls.rb before it has been defined by testcase.rb. Your code is functionally equivalent to the following:
$event = "/sendmessage/#{id}"
id = 100
puts $event
This does not work because you are attempting to call id before it has been defined. You must define the variable first:
id = 100
$event = "/sendmessage/#{id}"
puts $event
Here it works because you have defined id before you're trying to call it.
When troubleshooting a problem like this, consider how it would have to work if you were not separating it into different files.
So without knowing more about what you're trying to accomplish, just make sure you have defined a variable before you try to call it.

Syntax error in xpath expression having contains

List <WebElement> elt2=driver.findElements(By.xpath("//*[contains#className,'textInputContainers']"));
Also tried the version below:
List< WebElement > elt2 = driver.findElements(By.xpath("//*[contains#id,'txt']"));
contains() is a function and so must have () around its arguments.
So change
//*[contains#className,'textInputContainers']
to
//*[contains(#className,'textInputContainers')]
Note: A more robust way to test for a class name within a #class attribute can be found here: Xpath: Find element with class that contains spaces

Chef attributes "no implicit conversion of String into Integer"

I'm writing a chef recipe which simply creates a database config file, but I'm stumped simply access the attributes. I have a few PHP applications being deployed to each instance, and OpsWorks uses the same recipes for everyone, so I have a few different settings in the attributes file.
attributes/database-settings.rb
# API
default[:api][:path] = 'app/config/database.php';
default[:api][:host] = 'test';
default[:api][:database] = 'test';
default[:api][:username] = 'test';
default[:api][:password] = 'test';
recipes/database-settings.rb
Chef::Log.info("Database settings!");
node[:deploy].each do |application, deploy|
if node.has_key?(application)
Chef::Log.info("Application: #{application}");
path = node["api"]["path"]; # ERROR HAPPENING HERE
Chef::Log.info("Path: #{path}");
template path do
source "database.erb"
mode 0440
variables({
:host => node["api"]["host"],
:database => node["api"]["database"],
:username => node["api"]["username"],
:password => node["api"]["password"]
})
end
end
end
The error I'm getting is no implicit conversion of String into Integer. I've tried creating and accessing the settings in every way I can think of, such as...
node[:api][:path] # no implicit conversion of Symbol into Integer
node['api']['path'] # no implicit conversion of String into Integer
node[:api].path # undefined method `path' for #<Chef::Node::ImmutableArray:0x007fa4a71086e8>
node[application][:path] # no implicit conversion of Symbol into Integer
I'm sure there's something very obvious I'm doing wrong here, but I've tried everything I can think of an I just can't seem to find any way of getting this to work?! Ideally I'd like to use a variable where I can "api", but using an if/else wouldn't be too terrible for 3 apps...
That is a common error seen when you try to access an object thinking it is a hash, but is actually an array. In fact, from one of your errors, it can be read that node["api"] is a Chef::Node::ImmutableArray.
Ok so the problem wasn't really that I was accessing the config wrongly, it was that the different attribute files were all being merged into a single config and I didn't realise this.
I had these config files...
attributes/database_settings.rb
default[:api][:path] = 'app/config/database.php';
default[:api][:username] = 'example';
attributes/writable_directories.rb
default[:api] = ['public/uploads', 'storage/cache'];
When I tried to access default[:api][:path] I was actually accessing the array of directories when seemed to override the database settings attributes. Moving these into default[:directories][:api] and default[:database][:api][:path] etc fixed this.
Note that you will also get this error if you accidentally enter a space between "node" and the items indexing it:
node[:foo][:bar]
will work, while
node [:foo][:bar]
will throw this exception. It can be hard to spot.

No Error for Undefined Variable Used in Class Methods in PHP

I spent more than 10 hours to find out the typo for debugging my PHP program. I expected PHP would produce an error when using an undefined variable. But when it is used as an object in a method, it doesn't. Is there a reason for it?
<?php
$oClass = new MyClass;
// $oCless->tihs('key', 'taht'); //<-- triggers the error: Notice: Undefined variable
$oClass->tihs('key', 'taht');
echo $oClass->arr['key'];
class MyClass {
public $arr = array('key' => 'foo');
function tihs($key, $value) {
$tihs->arr[$key] = $value; //<-- this does not cause an error message.
}
}
?>
Normally if the error reporting level is set to E_ALL | E_STRICT (or E_ALL as of PHP 5.4.0) it should spit out an E_STRICT error. For instance, this code:
error_reporting(E_ALL | E_STRICT);
$tihs->adrr = 453;
Produces:
Strict Standards: Creating default object from empty value in [...]
Interestingly enough, if you specifically create an array instead of an ordinary variable as a property of an object that doesn't exist, e.g.:
error_reporting(E_ALL | E_STRICT);
$tihs->adrr[25] = 453;
No strict standards error is shown! It looks like this could potentially be something PHP folks might want to fix, because I'm not aware this is documented nor I think there's a legitimate reason for this behaviour.
For the record, in both cases regardless of the error a new stdClass is being created on the fly instead, like sberry mentions in his answer.
It is because of PHP trickery...
Under the covers, PHP is actually creating an object called tihs, adding an array to the object called arr and setting key to value.
Here is a print_r($tihs); after the assignment:
stdClass Object
(
[arr] => Array
(
[key] => taht
)
)
You seemed to have misspelt $oClass as $oCless
Agreed, $oCless instead of $oClass would give you an undefined variable error.
Also, "this" is a keyword in most languages and may be in php as well. You should refrain from using it so that it doesn't come out in other languages as a habit. You'll get way more errors if you're using "this" as function and variable names. You wouldn't even get things to compile.

Resources