I spent the last week reading and re-reading the pugixml documentation and I can find no method of retrieving the PCDATA with xpath.
Please explain would I pull the text from title:
<html><head><title>Hello!</title></head></html>
Last time I asked this question the only answers I got referred to generic xpath queries, rather than specifically to the pugixml library functions. I've read the xpath documentation thoroughly, so don't worry about educating me about it.
Thanks.
const char* text = doc.select_single_node("html/head/title/text()").node().value();
select_single_node selects the PCDATA node
.node() converts from xpath_node to xml_node (this is necessary since XPath nodes are either xml nodes or attributes)
.value() gets the value of the node (i.e. text).
What I did when I was fetching PCDATA i first found the node, and after that I called
node = retrive_xml_node_from_xpath();
node.first_child().value;
So for the example you show create an xpath to find the title node, and then get its first childs value.
Related
I would like to go through the whole xml document that I have, without depending in the actual id value, node name or attributes.
I use the msxml3 lib.
I would like to get a list of the main nodes in the xml, that are descendants of the main node.
<mainNode>
<firstNodeInList></firstNodeInList>
<secondNodeInList></secondNodeInList>
<thirdNodeInList></thirdNodeInList>
</mainNode>
I would like to get a list of the inside nodes, i.e. :
firstNodeInList->secondNodeInList->thirdNodeInList.
Thank you
Since no one responded, I had to find out the answer, which apperently is very simple.
The first line will get the document element, or the root element. The second will get the list of children of the root.
MSXML2::IXMLDOMElementPtr docElem = m_newFileDoc->documentElement;
MSXML2::IXMLDOMNodeListPtr nodes = docElem->childNodes;
I have a stylesheet that I developed in version 1.0. I needed to convert to version 2.0 to take advantage of some additional features. Now however, when I use the following syntax I get all the results instead of just the first one. This worked in v1.0 but does not work in v2.0:
//elementName[1]
Is there a simple fix?
That XPath will return the same nodes in both versions (namely all the elementName elements in the document that are the first child with that name in their respective parent elements), but
<xsl:value-of select="//elementName[1]"/>
will give different results. In XSLT 1.0 the behaviour of value-of when given a set of nodes is to output the value of the first node in the set in document order and ignore the others, but in 2.0 it will output the values of all of them, separated by spaces. If you want to restrict to the first item in the sequence you should do so explicitly with (....)[1].
Yes, the fix is simple...
(//elementName)[1]
This will give you the first occurrence. Your previous xpath was every elementName that was the first elementName child of its parent.
A good example from the spec:
NOTE: The location path //para[1] does not mean the same as the
location path /descendant::para[1]. The latter selects the first
descendant para element; the former selects all descendant para
elements that are the first para children of their parents.
Well I'm facing an issue here:
I use Selenium to automate test on my application, and I use the following code to fill a textbox:
driver.find_element_by_id("form_widget_serial_number").send_keys("example", u'\u0009')
All the textboxes have the same id (form_widget_serial_number) so it's impossible to select a specific textbox by using selection by id (the code above selects the first textbox and u'\u0009' changes the cursor position to the next textbox).
Anyway, how can I send values to the "current" textbox without using find_element_by_id or another selector, given that the cursor is in the current textbox?
There are several selectors available to you - Xpath and css in particular are very powerful.
Xpath can even select by the text of an element and then access its second sibling1:
elem = driver.find_element(:xpath, "//div[contains(text(), 'match this text')]/following-sibling::*[2]")
If you need to find the current element that has focus:
focused_elem = driver.switch_to.active_element
And then to find the next one:
elem_sibling = focused_elem.find_element(:xpath, "following-sibling::*")
Using this example, you could easily traverse any sequence of sequential elements, which would appear to solve your problem.
Take a close look at the structure of the page and then see how you would navigate to the element you need from a reference you can get to. There is probably an Xpath or css selector that can make the traversal across the document.
1 FYI, I'm using an old version of Selenium in Ruby, in case your version's syntax is different
My approach would be:
Get a list of all contemplable elements by the known id
Loop over them until you find a focused element
Use send_keys to write into that element
To get the focused element something like
get_element_index('dom=document.activeElement')
might work. See this question for more information.
Edit: If the list you get from 1. is accidently sorted properly the index of an element in this list might even represent the number of u'\u0009' you have to send to reach that specific element.
Use ActionChains utility to do that. Use following code:
from selenium.webdriver.common.action_chains import ActionChains
ActionChains(driver).send_keys("Hello").perform()
This isn't exactly what I want to do, but it's a simple case of the functionality I need. I want to alternate between processing nodes in one document and processing nodes in a temp document that was created during the processing of the original document. To do this, I want to "save" a node from the original document into the temp document so I can go back to it. I can easily "save" the node itself into the temp document, but being part of the temp document I can no longer do things like test if another node is an ancestor of that node in the original document.
I could imagine using generate-id to do this. I wouldn't save the node per se, but an id to it and then use the id to get back to the node within the original document. The problem with this approach is that I can't ask for the node whose generate-id is such and such. I could go through the tree and find it, but I'm looking for a simpler, faster access method.
Does one exist?
Thanks in advance.
Index every node of interest by its generate-id():
<xsl:key name="kNodeById" match="node()"
use="generate-id()"/>
and to get to the node by its id $vId:
key('kNodeById', $vId)
I have this bit of code:
typedef CComQIPtr<MSXML::IXMLDOMDocument2> XML_DocumentPtr;
then inside some class:
XML_DocumentPtr m_spDoc;
then inside some function:
XML_NodePtr rn=m_spDoc->GetdocumentElement();
I cannot find anywhere in the MSDN documentation what that GetDocumentElement() is supposed to do? Can anyone tell me why it doesn't seem to be part of IXMLDOMDocument2 interface?
And which interface does have it?
IXMLDocument2 inherits from IXMLDocument. The GetDocumentElement() method is defined in that interface. See here.
Basically GetdocumentElement returns the root element of the XML document.
The property is read/write. It returns
an IXMLDOMElement that represents the
single element that represents the
root of the XML document tree. It
returns Null if no root exists.
When setting the documentElement
property, the specified element node
is inserted into the child list of the
document after any document type node.
To precisely place the node within the
children of the document, call the
insertBefore method of theIXMLDOMNode.
The parentNode property is reset to
the document node as a result of this
operation.
GetdocumentElement returns the root element of the document or NULL if no root exists.