Flutter/Dart XML adding and inserting nodes

783

The first problem I see is that you reuse the builder multiple times. I agree that the error message is a bit misleading: the error happens because the previous <paragraphblock> it re-added to the new document. You probably intend to move the creation of the builder into your method so that it looks like:

XmlDocument buildParagraphXML() {
  final builder = new XmlBuilder();
  builder.element('paragraphblock', nest: () {
    // etc ...
  });
  return builder.build();
}

Then the next problem I see in the line document.children.add(buildParagraphXML()); that attempts to add a document to another document. If you start with a builder, then ideally you build the complete document with the builder. If you want to go your way, you have to extract the first element from the second document, copy it, and add it to your first document as such:

document.children.add(buildParagraphXML().firstChild.copy());

Note that while the above code works, the resulting document is not valid because it contains multiple root elements.

Share:
783
Gary Frewin
Author by

Gary Frewin

Updated on December 21, 2022

Comments

  • Gary Frewin
    Gary Frewin over 1 year

    I'm trying to get going with the XML library for Flutter but can't make sense of the readme section on inserting and adding nodes.

    The readme says "you need to first create a copy as otherwise an XmlParentError is thrown"... this is the error I am getting, but I don't understand what it means by creating a copy or how I would do that.

    My code is very simple at the moment:

        builder = new XmlBuilder();
        XmlDocument document = buildParagraphXML();
        print(document.toXmlString(pretty: true, indent: '\t')); //this prints the xml correctly
        document.children.add(buildParagraphXML());
        print(document.toXmlString(pretty: true, indent: '\t')); //this throws the XMLParentError
    
      buildParagraphXML() {
        builder.element('paragraphblock', nest: () {
          builder.attribute('paragraphid', '1');
          builder.attribute('title', 'Paragraph 1');
          builder.text('content of paragraph');
        });
        final paragraphXML = builder.build();
        return paragraphXML;
      }
    

    The first print returns the accurate XML as:

    <paragraphblock paragraphid="1" title="Paragraph 1">Your content here</paragraphblock>
    

    The second one should return:

    <paragraphblock paragraphid="1" title="Paragraph 1">Your content here</paragraphblock>
    <paragraphblock paragraphid="1" title="Paragraph 1">Your content here</paragraphblock>
    

    but throws the XML parent error. Unhandled Exception: Node already has a parent, copy or remove it first: but I don't understand what 'copy or remove it' means...

    I then would like to be able to add subnodes to each paragraph, and so on, deeper into the tree.

  • Gary Frewin
    Gary Frewin almost 4 years
    Great! I didn't realise I needed to add .firstChild. before .copy(). Saved me hours, thanks!