I am using XML DOM API in C++ to parse an XML file. I can't find any method to get the attribute value in a node element.
For example, in the following xml
<test>
<fruit count="10">
...
...
</fruit>
<test>
I need to get the count string("10") using XML APIs. Can anybody help me with some code snippets.
Use DOM Parser API to get attribute value count.
Refer below sample code:
//code to perform some process for parsing the input file and get rootElement
DOMNodeList* fruitNodes= rootElement->getElementsByTagName(XMLString::transcode("fruit"));
DOMNode* node = fruitNodes->item(0);
DOMElement* fruitElement = dynamic_cast <xercesc::DOMElement*>(node);
const XMLCh* attrValue = fruitElement->getAttribute(XMLString::transcode("count"));
you can get value 10 from attrValue using: string(XMLString::transcode(attrValue))
Based on http://msdn.microsoft.com/en-us/library/windows/desktop/ms754523(v=vs.85).aspx
Try something like:
pXMLDomNodeList = pXMLDocElement->selectNodes("/test/fruit/#count");
Related
I have a configuration file saver/loader. In addition to the expected data, there is a <CustomData> node. When saving the node, we'd simply have a std::string _customData and add it to the node, like this:
pugi::xml_document doc;
pugi::xml_node config = doc.append_child("OurConfig");
// save custom data
pugi::xml_node customData = config.append_child("CustomData");
customData.append_child(pugi::node_pcdata).set_value(_customData);
Our _customData was base64 encoded XML. It is provided from another part of the application. It must be a string, since the other part of the application uses different programming language (C#). As you can imagine, that became annoying, because it wasn't human readable. First step to fix this was simply to get rid of base64 in the app that provides _customData. So now we have readable version, which looks like this:
<?xml version="1.0"?>
<OurConfig>
<CustomData><CfgRoot>
<SomeValue name="External setting for foo" value="Foo"/>
<SomeValue name="External setting for bar" value="Bar"/>
</CfgRoot></CustomData>
</OurConfig>
But it could probably improve if the custom data was directly appended to XML tree instead of as string value. How can I append XML string as XML and not as string to pugixml tree?
Ie. the output I'd like:
<?xml version="1.0"?>
<OurConfig>
<CustomData>
<CfgRoot>
<SomeValue name="External setting for foo" value="Foo"/>
<SomeValue name="External setting for bar" value="Bar"/>
</CfgRoot>
</CustomData>
</OurConfig>
In the docs, there are three methods listed. I used the first one, making a convenience function like this:
bool AppendXMLString(pugi::xml_node target, const std::string& srcString)
{
// parse XML string as document
pugi::xml_document doc;
if (!doc.load_buffer(srcString.c_str(), srcString.length()))
return false;
for (pugi::xml_node child = doc.first_child(); child; child = child.next_sibling())
target.append_copy(child);
return true;
}
I've got an XML document that I receive from a REST service that I wish to parse. The service might change their element and tag names so I'm trying to come up with some completely generic solution that saves the document structure as some kind of object with attributes.
I'm not sure how/if the C++ and Qt API's allow me to accomplish such a thing however. I've thought of creating some kind of keyed map that can hold element names as string keys and values would be their children in some recursive fashion. Being very new to Qt and C++ I'm not sure how I can accomplish this.
This could be an example XML document:
<root>
<element id="1">
<name>SomeName</name>
<desc>SomeDesc</desc>
<params>
<param pid="1">True</param>
<param pid="2">False</param>
</params>
...
<Some unknown element></Some unknown element>
</element>
</root>
This is how I convert the HTTP response (QNetworkReply) to a DOM document I can use in Qt:
QByteArray data = reply->readAll();
QDomDocument doc;
doc.setContent(data);
QDomNodeList nodes = doc.elementsByTagName("root");
if (nodes.size() > 0) {
// Prints all elements, should be able to save in a map somehow? Perhaps there is a better way?
qDebug() << nodes.at(0).toElement().text();
}
I would love some input on how I can parse this in a way that allows me to keep all information in the XML even without knowing the element, attribute and tag names. Something like this:
element = {
id : 1,
name : 'SomeName',
desc : 'SomeDesc',
params : [{
pid : 1,
param : True
}, {
pid : 2,
param : False
}
],
some unknown element : some unknown values
}
I want to create an XML document by building a DOM document from scratch, with syntax like:
AutoPtr<Document> doc = new Document;
AutoPtr<Element> root = doc->createElement("root");
doc->appendChild(root);
AutoPtr<Element> element1 = doc->createElementNS("http://ns1", "ns1:element1");
root->appendChild(element1);
AutoPtr<Element> element2 = doc->createElementNS("http://ns1", "ns1:element2");
root->appendChild(element2);
DOMWriter writer;
writer.setNewLine("\n");
writer.setOptions(XMLWriter::PRETTY_PRINT);
writer.writeNode(std::cout, doc);
But, when I write it, I get next result:
<root>
<ns1:element1 xmlns:ns1="http://ns1"/>
<ns1:element2 xmlns:ns1="http://ns1"/>
</root>
So namespace ns1 declared two times, and I want to declare it inside "root" element.
Is there way to get next representation:
<root xmlns:ns1="http://ns1"/>
<ns1:element1/>
<ns1:element2/>
</root>
Using the MSXML2 functions from the "msxml3.dll" library, I'm trying to duplicate sections in an XML document, but it does not work as I expected.
Here is the XML:
<result>
<Target>
<Point>
<pos dimension="2">60.384005 5.333862</pos>
</Point>
</Target>
</result>
What I want is to add multiple sections. So I want to take the node, duplicate it and put it under the existing <Target> node. I'm almost convinced I should use the Clone method, but it does not seem to work.
The C++ code:
typedef MSXML2::IXMLDOMNodePtr XmlNode;
XmlNode pNode = pXMLRequest->selectSingleNode("//result");
if(pNode==NULL)
{ m_szErrorText = m_szErrorText + _T(" 'result' node not found");return FALSE;}
XmlNode pTargetNode = pNode->selectSingleNode("Target");
XmlNode pNewTargetNode = pTargetNode->cloneNode(true);
pNode->appendChild(pNewTargetNode);
But when I run this code nothing happens to the XML document. And when I inspect the XML text in pNewTargetNode I see it is '<result>' only which is just the name of the node While I would expect it to contain all the nodes in <Target>...</Target>. Is there something I am missing ?
I used the wrong kind of 'true'.
If I replace
XmlNode pNewTargetNode = pTargetNode->cloneNode(true);
with
XmlNode pNewTargetNode = pTargetNode->cloneNode(VARIANT_TRUE);
it works fine. I had already thought about this and used TRUE instead of true, but that does not work either.
So when using the msxml library alsways use VARIANT_BOOL, VARIANT_FALSE and VARIANT_TRUE.
Raymond Chen explains why there are so many variations:
http://blogs.msdn.com/b/oldnewthing/archive/2004/12/22/329884.aspx
Here is my code which i wrote in onRequestscript
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
path = "D:\\Service\\something2.xml";
log.info("path = "+ path);
if (mockRequest.method == "POST" )
{
mockRunner.returnFile( mockRequest.httpResponse, new File(path))
return new com.eviware.soapui.impl.wsdl.mock.WsdlMockResult(mockRequest)
}
But this script changes my XML entirely... I want to modify an existing XML(something.xml)..
i was actually Not able to modify the xml so i thought of changinf the xml instead.But according to my business logic its wrong... So can any one help me to modify the xml
in onRequestscript....
XML like
<Something>
<Data1>
<value>100</value>
<Data1>
<Data2>
<value>200</value>
<Data2>
</Something>
to a modified like this
<Something>
<Data1>
<value>101</value>
<Data1>
<Data2>
<value>201</value>
<Data2>
</Something>
You can use XmlSlurper to parse and update values from XML file. Then generate a string from updated XML and set it to the response of your mock service.
I use free SoapUI 3.6.1 but it seems that its output object differs from your example. Revise the code for your needs.
// get and parse XML file content
path = "D:\\Service\\something2.xml";
def doc = new XmlSlurper().parse(path)
// update values
doc.Data1.value[0] = 101
doc.Data2.value[0] = 201
// generate and return XML string as service response
import groovy.xml.StreamingMarkupBuilder
def result = new StreamingMarkupBuilder().bind{ mkp.yield doc }.toString()
mockResponse.setResponseContent(result)