Spoon
28th March 2011, 18:24
I have three xml files I'd like to merge.
base.xml
<symbols>
<circle>
<n_points>0</n_points>
</circle>
</symbols>
rect.xml
<rectangle>
<points>
<n_points>4</n_points>
<point>
<x>1.0</x>
<y>2.0</y>
</point>
<point>
<x>6.0</x>
<y>2.0</y>
</point>
<point>
<x>1.0</x>
<y>4.0</y>
</point>
<point>
<x>6.0</x>
<y>4.0</y>
</point>
</points>
</rectangle>
3d.xml
<rectangle>
<points>
<point>
<z>7.0</z>
</point>
<point>
<z>8.0</z>
</point>
<point>
<z>9.0</z>
</point>
<point>
<z>10.0</z>
</point>
</points>
</rectangle>
I want the end result to be like this...
<symbols>
<circle>
<n_points>0</n_points>
</circle>
<rectangle>
<points>
<n_points>4</n_points>
<point>
<x>1.0</x>
<y>2.0</y>
<z>7.0</z>
</point>
<point>
<x>6.0</x>
<y>2.0</y>
<z>8.0</z>
</point>
<point>
<x>1.0</x>
<y>4.0</y>
<z>9.0</z>
</point>
<point>
<x>6.0</x>
<y>4.0</y>
<z>10.0</z>
</point>
</points>
</rectangle>
</symbols>
I constructed the following method:
void DomHelper::merge(QDomNode mergeInto, const QDomNode &mergeFrom) {
bool foundMatchingNode = false;
QDomNodeList children = mergeInto.childNodes();
for (int i = 0; i < children.size(); ++i) {
if (children.at(i) == mergeFrom) {
foundMatchingNode = true;
break;
}
}
if (foundMatchingNode) {
DomElementContainer elements(mergeInto, mergeFrom.toElement().tagName());
foreach(QDomElement element, elements) {
QDomNodeList elementChildren = mergeFrom.childNodes();
int count = elementChildren.size();
for (int i = 0; i < count; ++i) {
merge(element, elementChildren.at(i));
}
}
} else {
mergeInto.appendChild(mergeFrom);
m_doc = mergeInto.ownerDocument;
}
DomElementContainer is just a class I made instead of using elementsByTagName() ... actually I borrowed it from someone else and modified it but still, it works.
m_doc is what I return to my QTreeView widget to view the result. The result is not what I want though and I've been staring at my code for too long so I can't figure out how to fix it either. I would greatly appreciate some help here.
One other issue is that the merge should be correctly done no matter the order although base.xml always exists before the others. So...
base << rect << 3d
shall produce the same output as....
base << 3d << rect
base.xml
<symbols>
<circle>
<n_points>0</n_points>
</circle>
</symbols>
rect.xml
<rectangle>
<points>
<n_points>4</n_points>
<point>
<x>1.0</x>
<y>2.0</y>
</point>
<point>
<x>6.0</x>
<y>2.0</y>
</point>
<point>
<x>1.0</x>
<y>4.0</y>
</point>
<point>
<x>6.0</x>
<y>4.0</y>
</point>
</points>
</rectangle>
3d.xml
<rectangle>
<points>
<point>
<z>7.0</z>
</point>
<point>
<z>8.0</z>
</point>
<point>
<z>9.0</z>
</point>
<point>
<z>10.0</z>
</point>
</points>
</rectangle>
I want the end result to be like this...
<symbols>
<circle>
<n_points>0</n_points>
</circle>
<rectangle>
<points>
<n_points>4</n_points>
<point>
<x>1.0</x>
<y>2.0</y>
<z>7.0</z>
</point>
<point>
<x>6.0</x>
<y>2.0</y>
<z>8.0</z>
</point>
<point>
<x>1.0</x>
<y>4.0</y>
<z>9.0</z>
</point>
<point>
<x>6.0</x>
<y>4.0</y>
<z>10.0</z>
</point>
</points>
</rectangle>
</symbols>
I constructed the following method:
void DomHelper::merge(QDomNode mergeInto, const QDomNode &mergeFrom) {
bool foundMatchingNode = false;
QDomNodeList children = mergeInto.childNodes();
for (int i = 0; i < children.size(); ++i) {
if (children.at(i) == mergeFrom) {
foundMatchingNode = true;
break;
}
}
if (foundMatchingNode) {
DomElementContainer elements(mergeInto, mergeFrom.toElement().tagName());
foreach(QDomElement element, elements) {
QDomNodeList elementChildren = mergeFrom.childNodes();
int count = elementChildren.size();
for (int i = 0; i < count; ++i) {
merge(element, elementChildren.at(i));
}
}
} else {
mergeInto.appendChild(mergeFrom);
m_doc = mergeInto.ownerDocument;
}
DomElementContainer is just a class I made instead of using elementsByTagName() ... actually I borrowed it from someone else and modified it but still, it works.
m_doc is what I return to my QTreeView widget to view the result. The result is not what I want though and I've been staring at my code for too long so I can't figure out how to fix it either. I would greatly appreciate some help here.
One other issue is that the merge should be correctly done no matter the order although base.xml always exists before the others. So...
base << rect << 3d
shall produce the same output as....
base << 3d << rect