Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QDocument has not expected behavior when creating elements
Forum Updated to NodeBB v4.3 + New Features

QDocument has not expected behavior when creating elements

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 3 Posters 299 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A.v.OA Offline
    A.v.OA Offline
    A.v.O
    wrote on last edited by
    #1

    Context

    I was trying to fix QFormBuilder::save(...) by adding putting the result into a buffer first and
    then into a QDocument like this just for the sake of context.

    void FormWriter::save(QIODevice* dev, QWidget* widget)
    {
    	// Create to DOM document for reading the builder XML output.
    	QDomDocument doc("sf::FormWriter");
    	// Scope for buffer to go out of when done.
    	{
    		// Write the UI file to a buffer device.
    		QBuffer buf;
    		// Open the buffer device.
    		buf.open(QIODeviceBase::WriteOnly);
    		// Save the form to the buffer device.
    		QAbstractFormBuilder::save(&buf, widget);
    		// Assign the
    		doc.setContent(buf.data());
    	}
    	// Fix the missing or broken stuff.
    	fixMissingProperties(widget, doc);
    	// Write the fix ui file.
    	dev->write(doc.toByteArray());
    }
    

    Since QFrame properties frameShadow and frameShape are not written to file in QFormBuilder.

    Problem

    I have used an XML DOM from other languages but for some reason the behavior is different then I expected.
    I seems that the return value of QDomNode::setAttributeNode(...) and QDomNode::appendChild(...)
    are not usable for adding elements or attributes.

    Not Working

    QDomElement getDomProperty(QDomDocument& dom, const QString& name, const QString& type, const QString& value)
    {
    	auto prop = dom.createElement("property");
    	prop.setAttributeNode(dom.createAttribute("name")).setValue(name);
    	prop.appendChild(dom.createElement(type)).appendChild(dom.createTextNode(value));
    	return prop;
    };
    

    Does Work

    QDomElement getDomProperty(QDomDocument& dom, const QString& name, const QString& type, const QString& value)
    {
    	auto prop = dom.createElement("property");
    	auto attr = dom.createAttribute("name");
    	attr.setValue(name);
    	prop.setAttributeNode(attr);
    	auto enu = dom.createElement(type);
    	prop.appendChild(enu);
    	enu.appendChild(dom.createTextNode(value));
    	return prop;
    };
    

    Questions

    • Is this normal behavior?
    • If so what is the purpose of the return value?
      (Took me a few hours to find out it wasn't working.)
    sierdzioS JonBJ 2 Replies Last reply
    0
    • A.v.OA A.v.O

      Context

      I was trying to fix QFormBuilder::save(...) by adding putting the result into a buffer first and
      then into a QDocument like this just for the sake of context.

      void FormWriter::save(QIODevice* dev, QWidget* widget)
      {
      	// Create to DOM document for reading the builder XML output.
      	QDomDocument doc("sf::FormWriter");
      	// Scope for buffer to go out of when done.
      	{
      		// Write the UI file to a buffer device.
      		QBuffer buf;
      		// Open the buffer device.
      		buf.open(QIODeviceBase::WriteOnly);
      		// Save the form to the buffer device.
      		QAbstractFormBuilder::save(&buf, widget);
      		// Assign the
      		doc.setContent(buf.data());
      	}
      	// Fix the missing or broken stuff.
      	fixMissingProperties(widget, doc);
      	// Write the fix ui file.
      	dev->write(doc.toByteArray());
      }
      

      Since QFrame properties frameShadow and frameShape are not written to file in QFormBuilder.

      Problem

      I have used an XML DOM from other languages but for some reason the behavior is different then I expected.
      I seems that the return value of QDomNode::setAttributeNode(...) and QDomNode::appendChild(...)
      are not usable for adding elements or attributes.

      Not Working

      QDomElement getDomProperty(QDomDocument& dom, const QString& name, const QString& type, const QString& value)
      {
      	auto prop = dom.createElement("property");
      	prop.setAttributeNode(dom.createAttribute("name")).setValue(name);
      	prop.appendChild(dom.createElement(type)).appendChild(dom.createTextNode(value));
      	return prop;
      };
      

      Does Work

      QDomElement getDomProperty(QDomDocument& dom, const QString& name, const QString& type, const QString& value)
      {
      	auto prop = dom.createElement("property");
      	auto attr = dom.createAttribute("name");
      	attr.setValue(name);
      	prop.setAttributeNode(attr);
      	auto enu = dom.createElement(type);
      	prop.appendChild(enu);
      	enu.appendChild(dom.createTextNode(value));
      	return prop;
      };
      

      Questions

      • Is this normal behavior?
      • If so what is the purpose of the return value?
        (Took me a few hours to find out it wasn't working.)
      sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      @A-v-O said in QDocument has not expected behavior when creating elements:

      Is this normal behavior?

      Yes, normal and documented.

      If so what is the purpose of the return value?
      (Took me a few hours to find out it wasn't working.)

      See the documentation, it explains everything.

      If the element has another attribute that has the same name as newAttr, this function replaces that attribute and returns it; otherwise the function returns a null attribute.

      QDomElement's methods do not return references to self, so linking them with . won't work.

      (Z(:^

      1 Reply Last reply
      0
      • A.v.OA Offline
        A.v.OA Offline
        A.v.O
        wrote on last edited by
        #3

        @sierdzio said in QDocument has not expected behavior when creating elements:

        QDomElement's methods do not return references to self, so linking them with . won't work.

        Maybe I missed something in the documentation on QDomNode::insertBefore(...) .
        In my view it exactly does what I expect of it and returns a usable instance to work with.

        I know it does not return it self but it returns a new instance
        of QDomNode referencing the same reference as the passed newChild.

        Before I posted I looked at the source code of QDomNode::insertBefore(...) and the
        code of QDomNodePrivate::insertBefore(...) .

        And I don't see where it says calling appendChild() returns something which is unusable.

        QDomNode QDomNode::appendChild(const QDomNode& newChild)
        {
            if (!impl) {
                qWarning("Calling appendChild() on a null node does nothing.");
                return QDomNode();
            }
            return QDomNode(IMPL->appendChild(newChild.impl));
        }
        

        Code above calls method below.

        QDomNodePrivate* QDomNodePrivate::appendChild(QDomNodePrivate* newChild)
        {
            // No reference manipulation needed. Done in insertAfter.
            return insertAfter(newChild, nullptr);
        }
        

        And this above calls insertAfter(...) .

        QDomNodePrivate* QDomNodePrivate::insertAfter(QDomNodePrivate* newChild, QDomNodePrivate* refChild)
        {
            //
            // Lots of manipulation but no reassignment of the newChild parameter.
            //
            return newChild;
        }
        

        So where does my reasoning go wrong?

        1 Reply Last reply
        0
        • sierdzioS Offline
          sierdzioS Offline
          sierdzio
          Moderators
          wrote on last edited by
          #4

          @A-v-O said in QDocument has not expected behavior when creating elements:

          QDomNode QDomNode::appendChild(const QDomNode& newChild)

          This:

          QDomNode QDomNode::appendChild(const QDomNode& newChild)
          

          Returns a copy of QDomNode. If you want to modify original object (like is usually the case with chained calls) it would have to return a reference QDomNode& QDomNode::appendChild().

          So, looking back at your original code:

          prop.appendChild(dom.createElement(type)).appendChild(dom.createTextNode(value));
          

          You add a new child to prop (which in working code you call enu). Then you add another child to a copy of enu - but it is not added to the original item.

          (Z(:^

          A.v.OA 1 Reply Last reply
          3
          • A.v.OA A.v.O

            Context

            I was trying to fix QFormBuilder::save(...) by adding putting the result into a buffer first and
            then into a QDocument like this just for the sake of context.

            void FormWriter::save(QIODevice* dev, QWidget* widget)
            {
            	// Create to DOM document for reading the builder XML output.
            	QDomDocument doc("sf::FormWriter");
            	// Scope for buffer to go out of when done.
            	{
            		// Write the UI file to a buffer device.
            		QBuffer buf;
            		// Open the buffer device.
            		buf.open(QIODeviceBase::WriteOnly);
            		// Save the form to the buffer device.
            		QAbstractFormBuilder::save(&buf, widget);
            		// Assign the
            		doc.setContent(buf.data());
            	}
            	// Fix the missing or broken stuff.
            	fixMissingProperties(widget, doc);
            	// Write the fix ui file.
            	dev->write(doc.toByteArray());
            }
            

            Since QFrame properties frameShadow and frameShape are not written to file in QFormBuilder.

            Problem

            I have used an XML DOM from other languages but for some reason the behavior is different then I expected.
            I seems that the return value of QDomNode::setAttributeNode(...) and QDomNode::appendChild(...)
            are not usable for adding elements or attributes.

            Not Working

            QDomElement getDomProperty(QDomDocument& dom, const QString& name, const QString& type, const QString& value)
            {
            	auto prop = dom.createElement("property");
            	prop.setAttributeNode(dom.createAttribute("name")).setValue(name);
            	prop.appendChild(dom.createElement(type)).appendChild(dom.createTextNode(value));
            	return prop;
            };
            

            Does Work

            QDomElement getDomProperty(QDomDocument& dom, const QString& name, const QString& type, const QString& value)
            {
            	auto prop = dom.createElement("property");
            	auto attr = dom.createAttribute("name");
            	attr.setValue(name);
            	prop.setAttributeNode(attr);
            	auto enu = dom.createElement(type);
            	prop.appendChild(enu);
            	enu.appendChild(dom.createTextNode(value));
            	return prop;
            };
            

            Questions

            • Is this normal behavior?
            • If so what is the purpose of the return value?
              (Took me a few hours to find out it wasn't working.)
            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by
            #5

            @A-v-O said in QDocument has not expected behavior when creating elements:

            prop.setAttributeNode(dom.createAttribute("name")).setValue(name);
            

            And in this case the setAttributeNode() docs show it returns the attribute node it is replacing, or a dummy node, and that's what you setValue() `on.

            Qt's stuff does work and as documented so not unexpected, just not to the chaining expectations you have have from, say, jQuery or whichever XML DOMs.

            A.v.OA 1 Reply Last reply
            0
            • sierdzioS sierdzio

              @A-v-O said in QDocument has not expected behavior when creating elements:

              QDomNode QDomNode::appendChild(const QDomNode& newChild)

              This:

              QDomNode QDomNode::appendChild(const QDomNode& newChild)
              

              Returns a copy of QDomNode. If you want to modify original object (like is usually the case with chained calls) it would have to return a reference QDomNode& QDomNode::appendChild().

              So, looking back at your original code:

              prop.appendChild(dom.createElement(type)).appendChild(dom.createTextNode(value));
              

              You add a new child to prop (which in working code you call enu). Then you add another child to a copy of enu - but it is not added to the original item.

              A.v.OA Offline
              A.v.OA Offline
              A.v.O
              wrote on last edited by
              #6

              @sierdzio said in QDocument has not expected behavior when creating elements:

              You add a new child to prop (which in working code you call enu). Then you add another child to a copy of enu - but it is not added to the original item.

              If you look too the Qt's source code and header of qdom.h (== link)
              Clearly method QDomNode::insertBefore(...) returns a new QDomNode but referencing the same actual node.

              Look at the source of QDomNode which has only one private member QDomNodePrivate* impl;
              it references the implementation node.

              So QDomNode's only reference to an instance which contains the actual implementation node impl.
              You can have different QDomNode's which reference the same actual node.

              In other words you should not need an original QDomNode.

              1 Reply Last reply
              0
              • JonBJ JonB

                @A-v-O said in QDocument has not expected behavior when creating elements:

                prop.setAttributeNode(dom.createAttribute("name")).setValue(name);
                

                And in this case the setAttributeNode() docs show it returns the attribute node it is replacing, or a dummy node, and that's what you setValue() `on.

                Qt's stuff does work and as documented so not unexpected, just not to the chaining expectations you have have from, say, jQuery or whichever XML DOMs.

                A.v.OA Offline
                A.v.OA Offline
                A.v.O
                wrote on last edited by A.v.O
                #7

                @JonB said in QDocument has not expected behavior when creating elements:

                And in this case the setAttributeNode() docs show it returns the attribute node it is replacing, or a dummy node, and that's what you setValue() `on.
                Qt's stuff does work and as documented so not unexpected, just not to the chaining expectations you have have from, say, jQuery or whichever XML DOMs.

                You are right the QDomElement::setAttributeNode() does indeed not return a copy but a null attribute.

                Manual on QDomNode::insertAfter(...) states:

                Returns a new reference to newChild on success or a null node on failure.
                The DOM specification disallow inserting attribute nodes, but due to historical reasons QDom accept them nevertheless.

                My first interaction was the PHP XML Dom setAttribute(...) where the manual says:

                The new DOMAttr or false if an error occurred.

                Where I'm used to chain functions.

                Looking to the Java implementation, which I never worked with, does the same as Qt's implementation.

                Chaining makes it easy because local variables are superfluous in that case and for me it is more readable.

                Conclusion: My assumption was apparently incorrect.

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved