How can I get the value data out of an MSXML::IXMLDOMElement - c++

I have an xml string
<grandparent>
<parent>
<child>dave</child>
<child>laurie</child>
<child>gabrielle</child>
</parent>
</grandparrent>
What I want to get is the data raw xml that's inside the parent.
I'm using MSXML
iXMLElm->get_xml(&bStr);
is returning
<parent>
<child>dave</child>
<child>laurie</child>
<child>gabrielle</child>
</parent>
.
iXMLElm->get_text(&bStr);
returns
davelauriegabrielle
What function do I use if I want to get?
<child>dave</child>
<child>laurie</child>
<child>gabrielle</child>
Is anyone aware of some good documentation on these functions? Everything I've seen is a linked nightmare.

Iterate over the child nodes and build the string manually.

If you are using MSXML, this should be a case of getting the child node of the grandparent node.
So, if iXMLElm is the grandparent and it has only one child node, you can just use...
iXMLElm->get_firstChild(&iXMLChildElm)
...and then...
iXMLChildElm->get_xml(&bStr)
...to get the three child elements.
If there are multiple items under grandparent you could use selectSingleNode instead to use XPath for selecting the node with the inner XML you want.
The MSDN documentation is quite reasonable on the interfaces and calls available.

If you are using IXMLDOMElement, then
HRESULT getAttribute(
BSTR name,
VARIANT *value);
is the method in which 'name' is attribute name and 'value' is output parameter which will contain value of the attribute in string format.

Related

Deleting a node based on child value in Pugixml

What I have so far can delete all the children of the actual node I want to delete but not the node itself.
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file("config/config.xml");
pugi::xpath_query query_network_last_run("//state[network/network_last_run='2']");
pugi::xpath_node_set network_last_run = query_network_last_run.evaluate_node_set(doc);
The part below removes specific parts -- but I want to delete the network based on a child value (network_last_run), not this child of it.
network_last_run[0].node().remove_child("network_gateway");
XML file structure
<root>
<state>
<network>
<network_last_run>2<network_last_run>
<network_gateway>192.168.3.1</network_gateway>
</network>
</state>
</root>
I tried to step back up using
network_last_run[0].node().parent().remove_child("network");
But it seems that only modifies the actual structure stored in memory, (removes the first one) and not the structure the query has.
I could probably do this in a for loop and use an if condition to check whether the child node value matches, but I would like to do it through a query if possible?
After playing around with it a bit, this is the solution I made (and I couldn't find an answer to this anywhere else so I figured I could just post it here)
Essentially it changes the name of the actual node in question. After that, it runs a query (the node set of which could be used in a for loop) and removes any child elements with the new name.
network_last_run[0].node().set_name("removal");
pugi::xpath_query query_removals("//state");
pugi::xpath_node_set removals = query_removals.evaluate_node_set(doc);
removals[0].node().remove_child("removal");

Getting the main list of nodes from xml document, using msxml lib in c++

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;

Retrieving PCDATA xpath via the c++ pugixml library

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.

Xpath return node relative to another node

I have done a search for all nodes that have an attribute containing (substring) a String. These nodes can be found at different levels of the tree, sometimes 5 or 6 levels deep. I'd like to know what parent/ancestor node they correspond to at a specified level, 2 levels deep. The result for the search only should be much greater than the results for the corresponding parents.
EDIT to include code:
/xs:schema/xs:element/descendant::node()/#*[starts-with(., 'my-search-string-here')]
EDIT to clarify my intent:
When I execute the Xpath above sometimes the results are
/xs:schema/xs:element/xs:complexType/xs:attribute or
/xs:schema/xs:element/xs:complexType/xs:sequence/xs:element or
/xs:schema/xs:element/xs:complexType/xs:complexContent/xs:extension/xs:sequence/xs:element
These results indicate a place in the Schema where I have added application specific code. However, I need to remove this code now. I'm building an "adapter" schema that will redefine the original Schema (untouched) and import my schema. The String I am searching for is my prefix. What I need is the #name of the /xs:schema/node() in which the prefix is found, so I can create a new schema defining these elements. They will be imported into the adapter and redefine another schema (that I'm not supposed to modify).
To reiterate, I need to search all the attributes (descendants of /xs:schema/xs:element) for a prefix, and then get the corresponding /xs:schema/xs:element/#name for each of the matches to the search.
To reiterate, I need to search all the attributes (descendants of /xs:schema/xs:element) for a prefix, and then get the corresponding /xs:schema/xs:element/#name for each of the matches to the search.
/
xs:schema/
xs:element
[descendant::*/#*[starts-with(., 'my-search-string-here')]]/
#name
This should do it:
/xs:schema/xs:element[starts-with(descendant::node()/#*, 'my-search-string-here')]
You want to think of it as
select the xs:elements which contain a node with a matching attribute
rather than
select the matching attributes of descendant nodes of xs:elements, then work back up
As Eric mentioned, I need to change my thought process to select the xs:elements which contain a node with a matching attribute rather than select the matching attributes of descendant nodes of xs:elements, then work back up. This is critical. However, the code sample he posted to select the attributes does not work, we need to use another solution.
Here is the code that works to select an element that contains and attribute containing* (substring) a string.
/xs:schema/child::node()[descendant::node()/#*[starts-with(., 'my-prefix-here')]]

MSXML problem in VC++ 6

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.