XML adding the same element as a child (Getting HIERARCHY_REQUEST_ERR)

16,690

Solution 1

This is the problem:

childElement.appendChild(childElement);

You're trying to add a child element to itself. You can't do that. It doesn't make any sense to do that... an element can't be a child of itself. How would you expect that to be represented in the final XML?

If you change that code to

parent.appendChild(childElement);

or

childElement2.appendChild(childElement);

then it's fine.

Solution 2

You can add a <child> node as a child to <parent> and other <child> nodes. It is not allowed to add it to <family> or to the document directly. (rough guess - I'd need to see the schema or DTD)


Second - if you create elements for a document, always use this pattern:

Element element = doc.createElement("child");
Share:
16,690
rommel
Author by

rommel

Updated on November 21, 2022

Comments

  • rommel
    rommel over 1 year

    How do I add the same element as a child. I want something like this:

    <family>
      <parent name = "P1">
        <child name = "P1C1">
            <child name = "P1C1C1"/>
            <child name = "P1C1C2"/>
        </child>
        <child name = "P1C2"/>
        <child name = "P1C3">
          <child name = "P1C3C1"/>
        </child>
      </parent>
      <parent name = "P2">
        <child name = "P2C1">
            <child name = "P2C1C1"/>
        </child>
        <child name = "P2C2">
            <child name = "P2C2C1"/>
        </child>
      </parent>
    </family>
    

    If I try to create a child element and add another child to it I get:

    HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted.

    How can we generate the above XML tree?

    Also see the bigger picture for the solution I am building: Generate XML mapping of a recursive directory search

    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.transform.Result;
    import javax.xml.transform.Source;
    import javax.xml.transform.Transformer;
    import javax.xml.transform.TransformerFactory;
    import javax.xml.transform.dom.DOMSource;
    import javax.xml.transform.stream.StreamResult;
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    
    
    public class ChildofChildXML {
    
        public static void main(String[] args) {
            try {
                DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                DocumentBuilder docBuilder = factory.newDocumentBuilder();
                Document doc = docBuilder.newDocument();
                Element root = doc.createElement("family");   
                doc.appendChild(root);   
    
                Element parent = doc.createElement("parent");
                parent.setAttribute("name","P1");
                root.appendChild(parent);
    
                Element childElement = doc.createElement("child");
                childElement.setAttribute("name","P1C1");
                parent.appendChild(childElement);
    
    
                Element childElement2 = doc.createElement("child"); //Works
                childElement2.setAttribute("name","P1C1C1");
                childElement.appendChild(childElement2);
    
                /*
                childElement = doc.createElement("child");
                childElement.setAttribute("name","P1C1C1");
    
                // Not allowed - HIERARCHY_REQUEST_ERR: 
                childElement.appendChild(childElement); 
                */
    
                childElement = doc.createElement("child");
                childElement.setAttribute("name","P1C2");
                parent.appendChild(childElement);
    
                TransformerFactory tranFactory = TransformerFactory.newInstance();
                Transformer aTransformer = tranFactory.newTransformer();
                aTransformer.setOutputProperty("indent", "yes");
    
                Source src = new DOMSource(doc);
                Result dest = new StreamResult(System.out);
                aTransformer.transform(src, dest);  
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
    }
    

    Now the code needs to be merged with a recursive 'expand archive' call and that is where I am wondering how to add child of child as I need to apply the solution to recursion - where I am expanding a top level archive file using java.util.zip. The here is equivalent of the folder that contains the top level archive that being the parent and subsequent nodes are equivalent of the contents of the archives recursively. So an ear could have a war or a jar. The war could have jsp under it and WEB-INF/lib/x.jar and WEB-INF/lib/x.jar needs to be expanded again and so on and this child --> child --> child relationship is to be built up from the parent.

    • Jon Skeet
      Jon Skeet about 12 years
      Please show the code which is failing... and is this in a specific DTD?
    • rommel
      rommel about 12 years
      I have added a simple code and also the bigger picture of the requirement with a link.
  • rommel
    rommel about 12 years
    Hi @Jon Skeet - I am looking at best approach to use when dealing with a recursive look-up of a directory for sub-directories and mapping the contents of each dir with parent, and the parent and child dir will have the same element name. Content could be another sub-directory and files. When a sub dir is encountered it should be mapped with its parent and recursive method invocation should know the parent element. Recursive look-up is losing track of the parent and that must not close till the time all sub-dirs are mapped recursively.
  • rommel
    rommel about 12 years
    Hi @Andreas_D - I stated the problem details in response to the post by Jon Skeet on losing the element reference heirarchy while making a recursive call to the same function that looks up sub-directoies and needs to map parent dir with child, all with same element name.