creating xml element with two namespaces using libxml APIs - libxml2

I want to create an xml element having two namespace as below:
element name="Root" xmlns:xsi="myXSI" xmlns:xsd="myXSD"
I have checked out with the existing APIs, but it is not getting in this form. I am getting as
Root xmlns:xsd:xsi="myXSI" xmlns:xmlns:xsd="myXSD"
I am using this APIss as below:
xmlTextWriterWriteAttributeNS(xmlWriter, BAD_CAST "xmlns:xsd", BAD_CAST "xsi" , BAD_CAST "myXSD", BAD_CAST "myXSI");

Try
xmlTextWriterWriteAttributeNS(xmlWriter, BAD_CAST "xmlns", BAD_CAST "xsi", NULL, BAD_CAST "myXSI");
xmlTextWriterWriteAttributeNS(xmlWriter, BAD_CAST "xmlns", BAD_CAST "xsd", NULL, BAD_CAST "myXSD");

Related

to parse xml node children values under same tagname

I have two nodes PW_KeyGrip and PW_PalmerGrasp and the node children names are same in both the nodes.
<PW_KeyGrip>
<PW_p1_EDC>173</PW_p1_EDC>
<PW_p2_EDC>78</PW_p2_EDC>
<PW_p2_FDS>196</PW_p2_FDS>
</PW_KeyGrip>
<PW_PalmerGrasp>
<PW_p1_EDC>202</PW_p1_EDC>
<PW_p1_APB>118</PW_p1_APB>
<PW_p2_EDC>86</PW_p2_EDC>
</PW_PalmerGrasp>
earlier, I used to search by tag name in order to select the value as:
root.elementsByTagName("PW_p1_EDC").at(0).firstChild().nodeValue()
Now since I have two values under same tag name. can you show me a way to select both the values under same tag name separately?
for example:
How to select PW_p1_EDC under PW_KeyGrip
How to select PW_p1_EDC under PW_PalmerGrasp
You could use a simple function to retrieve the node value under a given tag name:
int findValue(QDomElement const& root, QString const& name)
{
QDomElement element = root.firstChildElement(name);
return element.firstChildElement("PW_p1_EDC").firstChild().nodeValue().toInt();
}
Then you would have to call it like that:
qDebug() << "PW_KeyGrip: " << findValue(root, "PW_KeyGrip");
qDebug() << "PW_PalmerGrasp: " << findValue(root, "PW_KeyGrip");
If you want to find the values without the exact path, you could take a look to XPath and QXmlQuery

InstallScript and machine.config

I'm having a couple of issues with InstallScript that I can not seem to figure out. The main one is that I need to add the following to the machine.config file:
<system.transactions>
<machineSettings maxTimeout="02:00:00" />
</system.transactions>
but it is adding it as such:
<system.transactions>
<machineSettings>
<maxTimeout>"02:00:00"</maxTimeout>
</machineSettings>
</system.transactions>
Here is the code I'm using to update the file (the messages boxes are for debugging purposes).
function STRING GetMachineConfigPath(hMSI)
STRING strRetVal;
NUMBER nSize, nType;
begin
nSize = MAX_PATH - 1;
MsiGetProperty(ISMSI_HANDLE, "MACHINECONFIGPATH", strRetVal, nSize);
return strRetVal;
end;
function SaveMachineConfigSettings(hMSI)
OBJECT oDoc; // XML Document object
OBJECT oNode; // A node in the XML DOM tree
OBJECT CurrParent; // Current parent node
STRING szFilename;
BOOL successfulLoad;
begin
szFilename = GetMachineConfigPath(hMSI) + "config\\machine.config";
if Is(FILE_EXISTS, szFilename) = FALSE then
MessageBox("Could not find machine.config file.", 0);
return -1;
endif;
set oDoc = CreateObject("Msxml2.DOMDocument");
if (IsObject(oDoc) = FALSE) then
MessageBox("Could not open machine.config file.", 0);
return -1;
endif;
oDoc.Async = FALSE;
oDoc.setProperty("SelectionLanguage", "XPath");
successfulLoad = oDoc.load(szFilename);
MessageBox("File loaded successfully.", 0);
if (successfulLoad = FALSE) then
MessageBox("File did not load successfully.", 0);
return -1;
endif;
set CurrParent = oDoc.documentElement;
set oNode = AddSetting(oDoc, CurrParent, "system.transactions", "");
set CurrParent = oNode;
set oNode = AddSetting(oDoc, CurrParent, "machineSettings", "");
set CurrParent = oNode;
set oNode = AddSetting(oDoc, CurrParent, "maxTimeout", '"02:00:00"');
// Write the XML document to a file.
oDoc.save(szFilename);
MessageBox("File updated successfully.", 0);
set oNode = NOTHING;
set oDoc = NOTHING;
return 0;
end;
function OBJECT AddSetting(oDoc, oParent, szNodeName, szValue)
OBJECT oNode;
begin
// Add a carriage return & line feed to make the output easier to read.
set oNode = oDoc.createTextNode("\n");
oParent.appendChild(oNode);
// Create the new setting node and value.
set oNode = oDoc.createElement(szNodeName);
oNode.text = szValue;
oParent.appendChild(oNode);
MessageBox("Node created successfully.", 0);
return oNode;
end;
Any help you could provide is really appreciated!
I ended up creating a C# console application to modify the file and then running that EXE from the InstallShield installation. This gave me a lot more flexibility and control over the modifying of the file to avoid causing issues.

Set inner HTML using QDomDocument

How can I set the inner HTML in a QDomElement?
When I’m using QWebElement I have the method QWebElement::setInnerXml, there is some similar method in QDomElement?
There's no API to "inject" XML snippets as text into a QDomDocument (or QXmlStreamWriter). One has to use the API and create the nodes programmatically.
Assuming you have a string to start with, my current solution is to generate a DOM tree from it, import that tree in a fragment, then copy those in the right place (you must have an import which is why you need an intermediate fragment. Quite unfortunate if you ask me.)
// assuming that 'n' is the node you are replacing or at least inserting after
// 'parent' is the parent of 'n'
// 'result' is the string to replace 'n' or insert after 'n'
QDomDocument doc_text("snap");
doc_text.setContent("<text>" + result + "</text>", true, NULL, NULL, NULL);
QDomDocumentFragment frag(xml.createDocumentFragment());
frag.appendChild(xml.importNode(doc_text.documentElement(), true));
QDomNodeList children(frag.firstChild().childNodes());
const int max(children.size());
QDomNode previous(n);
for(int i(0); i < max; ++i)
{
QDomNode l(children.at(0));
parent.insertAfter(children.at(0), previous);
previous = l;
}
// if you are replacing, then delete node n as well
parent.removeChild(n);
Note that the <text> tag is used so that way result does not need to be a tag, it could just be text and it will still work.
Obviously, if you have a fragment or XML from another document to start with, ignore the code that creates that code in the doc_text object.

qt sqlite select statement

I decided to test sqlite db for my Qt application.
I have created the sqlite db file with the proper statements (create table etc. and Inserted some rows of data).
My problem is that when I execute a select statement I don't get any records.
This is the code I use:
qq.sprintf("SELECT * from descriptors WHERE descriptors.id=%d ",idx);
query.exec(qq);
if( query.isSelect() ){
while (query.next()){
int fff = query.value(0).toInt();
}}
The problem is that I never get inside the while loop. query.next() doesn't seem to work.
any hints?
thanks in advance,
Thodoris
p.s. I forgot to write my configuration so: Qt 4.7.3, windows 7, visual studio 2008
Other than the mistake hexa posted, query.isSelect() will always return true even if the query failed. You need to check the result of exec():
QSqlQuery query;
query.prepare( "SELECT * FROM descriptors WHERE id = ?" );
query.bindValue( 0, idx ); // assuming idx is an integer/long/QVariant value
if( !query.exec() )
{
// Error Handling, check query.lastError(), probably return
}
// Note: if you don't return in case of an error, put this into the else{} part
while( query.next() )
{
int fff = query.value( 0 ).toInt();
}
In my case, backward iteration over QSqlQueries worked. I think this could be a bug somewhere in the QSQLite Driver implementation.
QSqlQuery q = db.exec("SELECT * FROM Table");
if (q.last()) {
do {
// Do something with row...
} while (q.previous());
}

how to write a CDATA node using libxml2?

I'm using libxml2 to read/write xml files. Now I'm trying to write a CDATA node.
Here is what I tried:
nodePtr = xmlNewChild( parentPtr, NULL, "foo", NULL );
xmlNodeSetContentLen( nodePtr, "<![CDATA[\nTesting 1 < 2\n]]>", len );
However, this results in the following encoded text:
<foo><![CDATA[
Testing 1 < 2
]]></foo>
I'm thinking that perhaps there might be a CDATA-specific libxml2 API. Or maybe I have to call something else to tell libxml2 not to automatically encode the node content?
Figured it out. The trick is in knowing that CDATA text content is actually a child and not a part of the current node, and the critical API to call is xmlNewCDataBlock(). Using the same example as above:
nodePtr = xmlNewChild( parentPtr, NULL, "foo", NULL );
cdataPtr = xmlNewCDataBlock( doc, "Testing 1 < 2", 13 );
xmlAddChild( nodePtr, cdataPtr );
This will produce the following xml:
<foo><![CDATA[Testing 1 < 2]]></foo>
I cannot say for all versions of libxml2, but according to libxml2-2.9.4 the doc part of returning node of xmlNewChild comes from its parent. Also the parent of child node returned from xmlNewCDataBlock is set by doc parameter. So the following would be a good practice:
const char str[] = "said the kitty";
xmlNodePtr node = xmlNewNode(NULL, BAD_CAST "meow");
xmlNodePtr cdata_node = xmlNewCDataBlock(node->doc, BAD_CAST str, strlen(str));
xmlAddChild(node, cdata_node);
The resulting xml is
<meow><![CDATA[said the kitty]]></meow>
And it would not matter if node is part of an xmlDoc or not

Resources