views:

1626

answers:

3

Hi - I'm using this XPath to get the value of a field:

//input[@type="hidden"][@name="val"]/@value

I get several results, but I only want the first. Using

//input[@type="hidden"][@name="val"]/@value[1]

Doesn't work. Once I have this, how do I pick up the value in Greasemonkey? I am trying things like:

alert("val "+val.snapshotItem);

But I think that's for the node, rather than the string.

+6  A: 

For the XPath, try:

//input[@type="hidden" and @name="val" and position() = 1]/@value

For use in a GreaseMonkey script, do something like this:

var result = document.evaluate(
  "//input[@type='hidden' and @name='var' and position()=1]/@value",
  document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null
);

var hiddenval = result.snapshotItem(0);

if (hiddenval)
  alert("Found: " + hiddenval.nodeValue);  
else
  alert("Not found.");

Strictly speaking: Using "position()=1" in the XPath filter is not absolutely necessary, because only the first returned result is going to be used anyway (via snapshotItem(0)). But why build a larger result set than you really need.

EDIT: Using an XPath result of the ORDERED_NODE_SNAPSHOT_TYPE type makes sure you get the nodes in document order. That means the first node of the result will also be the first node in the document.

Tomalak
+4  A: 

Tomalak has the right idea, but I'd do it a bit differently.

var result = document.evaluate(
  "//input[@type='hidden' and @name='var']",
  document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);

var input = result.iterateNext();

if (input)
  alert("Found: " + input.value);  
else
  alert("Not found.");

This way, you're specifying as part of the result set that you want only one item returned (the first one in the document, in this case). Also, here you're fetching the DOM node and then reading its value property to get the value. I've found this to be more reliable than fetching a string value through XPath (though your mileage may vary).

savetheclocktower
You are right. I'll adapt my code a bit. I tend to forget that FF has XPath that is able to work out of document order. Thanks.
Tomalak
A: 

One possibility is to include jQuery in your scripts. This will provide a simpler syntax for accessing elements.

// ==UserScript==
// @name           MyScript
// @namespace      http://example.com
// @description    Example
// @include        *
//
// @require     http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js
// ==/UserScript==

var input = $("input[type='hidden'][name='var']");

if (input) {
  alert("Found: " + input.val());  
} else {
  alert("Not found.");
}
Daniel X Moore