Iterating through all nodes and attributes of a wxXmlDocument

42 views
Skip to first unread message

Tim Burgess

unread,
Feb 25, 2025, 8:25:50 AM2/25/25
to wx-u...@googlegroups.com

Hi,

 

It’s been a while since I had to recurse anything, but I can’t see how to do this. I’m trying to construct a wxString that represents the text content of a class derived from wxXmlDocument. Here’s what I have:

 

wxString MyDerivedXMLDocClass::GetTextContent()

              {

                             wxString result = wxEmptyString;

                             wxXmlNode* const root = this->GetRoot();

 

                             if (root == nullptr)

                             {

                                           return wxEmptyString;

                             }

 

                             return GetNodeText(root);

}

 

              wxString MyDerivedXMLDocClass::GetNodeText(wxXmlNode * myNode)

              {

                             wxString result = wxEmptyString;

                            

                             if (myNode->GetType() == wxXML_ELEMENT_NODE)

                             {

                                           result = myNode->GetName();

 

                                           // Get all attributes

                                           for (const wxXmlAttribute* attribute = myNode->GetAttributes(); attribute != NULL; attribute->GetNext())

                                           {

                                                          result += attribute->GetName() + attribute->GetValue() + "\n";

                                           }

                             }

                                           else if (myNode->GetType() == wxXML_TEXT_NODE)

                             {

                                           result += myNode->GetContent() + "\n";

                             }

 

for (wxXmlNode * childNode = myNode->GetChildren(); childNode != NULL; childNode->GetNext())

{

                             result += GetNodeText(childNode);

                                           }

return result;

              }

                            

 

The code throws an exception, but I can’t tell quite where as I’m a blind programmer and the exception blows out my screen reader.

 

Any advice would be most welcome.

 

Tim

 

Maarten Bent

unread,
Feb 25, 2025, 6:43:50 PM2/25/25
to wx-u...@googlegroups.com
Hi,

Looks like you have infinite iterations in both for-loops. Because you do not assign the next attribute/childNode.
For example, the last component in the second for loop should be: childNode = childNode->GetNext().

Maarten
--
Please read https://www.wxwidgets.org/support/mlhowto.htm before posting.
---
You received this message because you are subscribed to the Google Groups "wx-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wx-users+u...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/wx-users/005801db8788%24c5fa7870%2451ef6950%24%40raisedbar.net.

timbu...@gmail.com

unread,
Mar 7, 2025, 6:13:01 AM3/7/25
to wx-u...@googlegroups.com

Martin,

 

Many thanks for this and apologies for not replying sooner – your message landed in my Junk folder for reasons that are beyond me.

 

Best wishes.

 

Tim

Kenneth Porter

unread,
Mar 7, 2025, 1:03:02 PM3/7/25
to wx-u...@googlegroups.com
I wonder if a range adapter might make situations like this easier to
code? One might have something like this:

for (auto child : node->GetChildrenAsRange()) doSomethingWithNode(child);

for (auto attr : node->GetAttributesAsRange())
doSomethingWithAttribute(attr);

The adapter classes returned by the new APIs could be very simple child
classes of wxNode, defining a constructor, begin(), end(), the
preincrement operator, and the dereference operator.

The constructor could take an optional filter predicate that skips nodes
that don't match the predicate.



Kenneth Porter

unread,
Mar 7, 2025, 3:01:57 PM3/7/25
to wx-u...@googlegroups.com
Small correction. The auto in the ranged for loops should use a "forwarding reference" (double ampersands). This was added in C++11.
for (auto&& child : node->GetChildrenAsRange()) doSomethingWithNode(child);

for (auto&& attr : node->GetAttributesAsRange()) doSomethingWithAttribute(attr);

The forwarding reference, a feature of template parameters and auto, allow it to copy the const and volatile attributes of the argument.

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4164.pdf


Reply all
Reply to author
Forward
0 new messages