QDomNode Class read value of child in qt - c++

I want to change "A" in Apple, in key which value is 1 to "D", in this code 2 items should be replaced. I tried something like this, but nothing happens.
<C>
<B>
<Key value="1">
<Apple>A</Apple>
</Key>
<Key value="2">
<Apple>A</Apple>
</Key>
<Key value="3">
<Apple>A</Apple>
</Key>
<Key value="1">
<Apple>A</Apple>
</Key>
</B>
</C>
Qt:
QDomNodeList roots = doc.elementsByTagName("Key");
for (int i = 0; i < roots.size(); ++i) {
QDomElement domElement = roots.at(i).toElement();
QDomAttr attribute = domElement.attributeNode("value");
if (attribute.value() == "1") {
domElement.firstChild().setNodeValue("D");
}

In your code the domElement.firstChild() refers to the <Apple> element node, not to its content. The value inside the <Apple> is also a node (text node), that is why it is located one level deeper in the DOM hierarchy:
domElement — <Key>
domElement.firstChild() — <Apple>
domElement.firstChild().firstChild() — A
So you will also have to get the first child of the <Apple> element node:
domElement.firstChild().firstChild().setNodeValue("D");

Maybe:
if (attribute.value() == "1")

Related

Print all root to leaf path using recursion

I'm trying to print all root to leaf path using recursion, but I'm clueless
I don't know how to approach it, I'm completely stuck
<node id="N1">
<node id="N1">
<node id="N1"></node>
<node id="N2"></node>
<node id="N3"></node>
</node>
</node>
desired output :
N1 N1 N1
N1 N1 N2
N1 N1 N3
A simple
<xsl:value-of select="//node[not(*)]/string-join(ancestor-or-self::node/#id, ' ')" separator="
"/>
should do, without any need for recursion.

How do I combine the text value of multiple (same name) nodes and update another node if the combined length > 20 characters?

I would like to combine all Node2 values into a single Node2. However, if the combined string is greater than 20 characters, I want to append the combined string to Node1 and truncate Node2 to only 20 characters.
<Parent>
<Node1>Some Text</Node1>
<Node2>Some Name1</Node2>
<Node2>Some Name2</Node2>
<Node2>Some Name3</Node2>
<Node2>Some Name4</Node2>
<Node2>Some Name5</Node2>
</Parent>
The desired result is:
<Parent>
<Node1>Some Text; Node2: Some Name1, Some Name2, Some Name3, Some Name4, Some Name5</Node1>
<Node2>Some Name1, Some Nam</Node2>
</Parent>
Try the following XSLT-2.0 solution:
<xsl:template match="/Parent">
<xsl:copy>
<xsl:copy-of select="#*" />
<xsl:variable name="n2">
<xsl:value-of select="Node2" separator=", "/>
</xsl:variable>
<Node1><xsl:value-of select="Node1, if (string-length($n2) > 20) then concat('; Node2: ',$n2) else ''" separator=""/></Node1>
<Node2><xsl:value-of select="substring($n2,1,20)" /></Node2>
</xsl:copy>
</xsl:template>
Output is:
<?xml version="1.0" encoding="UTF-8"?>
<Parent>
<Node1>Some Text; Node2: Some Name1, Some Name2, Some Name3, Some Name4, Some Name5</Node1>
<Node2>Some Name1, Some Nam</Node2>
</Parent>

xslt multiple parameters into javascript

Im trying to create a function in javascript in xsl which accepts multiple in-parameters. I can not get it to work and get the following error:
Code: 0x80020009
Microsoft JScript runtime error
Wrong number of arguments or invalid property assignment
line = 37, col = 2 (line is offset from the start of the script block).
Error returned from property or method call.
The function looks as follows:
<msxsl:script language="JavaScript" implements-prefix="jsfuncs">
<![CDATA[
function getLineLength (x1,x2,y1,y2)
{
var xVector = x2 - x1;
var yVector = y2 - y1;
var output = Math.sqrt(raised2(xVector)+raised2(yVector));
return output;
}
]]>
</msxsl:script>
The calling code looks as follows:
<xsl:value-of select="jsfuncs:getLineLength($x1,$x2,$y1,$y2)"/>
x1,x2... are variables set earlier and they are correct. I can get everything to work when I post-process the values to one parameter. Is it at all possible to pass multiple parameters in xslt to Javascript? The engine in use is msxml 3.0.
Here is an example passing in four parameters:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ms="urn:schemas-microsoft-com:xslt"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="ms mf"
version="1.0">
<ms:script language="JScript" implements-prefix="mf">
function test(a, b, c, d) {
return a + ":" + b + ":" + c + ":" + d;
}
</ms:script>
<xsl:template match="/">
<xsl:value-of select="mf:test(1, 2, 3, 'foo')"/>
<br/>
<xsl:variable name="item" select="root/item"/>
<xsl:value-of select="mf:test(string($item/#a), string($item/#b), string($item/#c), string($item/#d))"/>
</xsl:template>
</xsl:stylesheet>
As you can see, when wanting to pass in a node to a function expecting a primitive value I would recommend to make sure to convert it on the XSLT side to a primitive value first, as done in mf:test(string($item/#a), string($item/#b), string($item/#c), string($item/#d)), as otherwise the function will get a node-set represented by some selection interface that you would need to iterate first.
The sample works fine for me with MSXML 3 and outputs 1:2:3:foo<br />1:2:3:whatever when run against an input sample with
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item a="1" b="2" c="3" d="whatever"/>
</root>

collect attributes and values into string list

I have xml data looking like this:
<persons>
<person key="M">John Doe</person>
<person key="N">Jane Doe</person>
</persons>
I want to collect them into a list of maps like
[[key: M, name: John Doe], [key: N, name: Jane Doe]]
and I use, after slurping the data into the variable 'p', using XmlSlurper:
p.collect { [key: it.#key.text(), name it.text()] }
but I get
[[key: MN, name: John DoeJane Doe]]
Obviously I do something very wrong, but I can't figure out what. I have tried a number of methods but get the same answer.
Try looking for children() from root node.
def xml = """
<persons>
<person key="M">John Doe</person>
<person key="N">Jane Doe</person>
</persons>
"""
def slurper = new XmlSlurper().parseText( xml )
assert [
[key:'M', name:'John Doe'],
[key:'N', name:'Jane Doe']
] == slurper.children().collect {
[ key: it.#key.text(), name: it.text() ]
}

Checking all values in the element are same

I have an xml like, values can be
<n1>value1</n1>
<n1>value1</n1>
<n1>value2</n1>
I need to check if all these values are same and if same I would need to assign it to another element. I am using XSLT v1.0.
Thanks,
Good question, +1.
Just use:
not(/*/n1[1] != /*/n1)
Assuming that all n1 elements are selected in a variable named $v, this can be expressed in just 14 characters-long XPath expression:
not($v[1] != $v)
Explanation 1:
By definition:
/*/n1[1] != /*/n1
is true() exactly if there exists a node in /*/n1 whose string value isn't equal to the string value of /*/n1[1]
The logical negation of this:
not(/*/n1[1] != /*/n1)
is true() iff no node in /*/n1 exists whose string value isn't equal to the string value of /*/n1[1] -- that is, if all nodes in /*/n1 have the same sting value.
Explanation 2:
This follows from a more general double negation law :
every x has property y
is equivalent to:
There is no x that doesn't have property y
Assume a document of this form:
<root>
<n1>value1</n1>
<n1>value1</n1>
<n1>value1</n1>
</root>
The following simple stylesheet determines whether every n1 element has the same value:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:value-of select="
concat('All same? ', count(/*/n1[.=/*/n1[1]])=count(/*/n1))"/>
</xsl:template>
</xsl:stylesheet>
Output:
All same? true
The key to this stylesheet is the expression:
count(/*/n1[.=/*/n1[1]])=count(/*/n1))
...which compares the count of the n1 elements whose value equals the value of the first n1 element to the count of all n1 elements. These counts will be equal only when every n1 node has the same value.
This can be made a little easier to read by first selecting all n1 into a variable named n:
count($n[.=$n[1]])=count($n)
Conditionally perform some action based on the result like this:
<xsl:template match="/">
<xsl:variable name="all" select="count(/*/n1[.=/*/n1[1]])=count(/*/n1)"/>
<xsl:if test="$all">All same</xsl:if>
<xsl:if test="not($all)">Not all same</xsl:if>
</xsl:template>