-1

I have XML:

<SyncMXAUTHCI>
  <MXAUTHCISet>
    <CI>
      <CINAME>COMPUTER68</CINAME>
      <CIRELATION>INSTALLED</CIRELATION>
    </CI>
  </MXAUTHCISet>
</SyncMXAUTHCI>

I would like to have duplicate content of MXAUTHCISet. Result would be:

<SyncMXAUTHCI>
  <MXAUTHCISet>
    <CI>
      <CINAME>COMPUTER68</CINAME>
    </CI>
    <CI>
      <CINAME>COMPUTER68</CINAME>
      <CIRELATION>INSTALLED</CIRELATION>
    </CI>
  </MXAUTHCISet>
</SyncMXAUTHCI>

How to do it? I tried with .addContent, .setContnet methods but without success. How to aachieve this? Thank you

UPDATE: I take elements in this form:

Document erJdom = erData.getData();
Element root = erJdom.getRootElement();
Namespace erJdomNamespace = root.getNamespace();

Element incidentSet = root.getChild("MXAUTHCISet", erJdomNamespace);

Element incident=incidentSet.getChild("CI", erJdomNamespace);

That work ok. But when I try:

Element incident=incidentSet.getChild("CI", erJdomNamespace);
Element ci2=new Element("CI");
ci2.addContent(incident);

So you can see that I try to take element content and to put it in new element with the same content which will i add on MXAUTHSet ERROR I am getting: The Content already has an existing parent "MXAUTHCISet"

so it even does not come to the part where I want to add that new element:

incidentSet.addContent(ci2);
ja jaaaa
  • 115
  • 4
  • 15

2 Answers2

2

You cannot add any JDOM content to any Element if that content is already attached to an Element.

The easiest thing for you to do is use the clone() method which creates an un-attached duplicate.

In your case:

incidentSet.addContent((Element)incidentSet.getChild("CI", erJdomNamespace).clone());

(If you were using JDOM 2.0.x the clone() method will return an Element... and the (Element) case would be unnecessary)

rolfl
  • 17,539
  • 7
  • 42
  • 76
  • This looks promising. But my JDOM returns OBJECT. Is that the problem? What can be the workaround? – ja jaaaa May 07 '13 at 14:16
  • "The method addContent(String) in the type Element is not applicable for the arguments (Object)" – ja jaaaa May 07 '13 at 14:19
  • If your JDOM returns Object, then you are using JDOM 1.x versions. This is OK, but not great. If you upgrade to JDOM 2.x, you can avoid having to cast the Object to an Element. I will edit the answer with a cast in it. – rolfl May 07 '13 at 14:19
  • I am sending new class to server. I will give you back result I am having. I hope it will work now – ja jaaaa May 07 '13 at 14:39
  • This is great it works. Can I please just ask you one more thing (REALLY SORRY). I did all this because I want to delete some element in first CI but to keep it in second CI. is it possible? You can see CIRELATION element. Can I somehow keep the content of the first one and to put it in second element and than to delete CIRELATION element? You can see in update how it looks like. REALLY SORRY AND FOR QUESTION YOU HELPED ME A LOT!! – ja jaaaa May 07 '13 at 14:46
  • I know I will use REMOVECHILD method but I am interested in how to keep it in second before I remove from the first element – ja jaaaa May 07 '13 at 14:50
  • Once you have cloned() the second instance, they are independent. Changes you make to one will not be seen in the other. – rolfl May 07 '13 at 14:51
  • yes but let me explain it more deeper: On example I have 3 CI. I duplicate it now I have 6. Now I want to do removeChild("CIRELATION") but only on first 3 elements not and on the other 3 CI elements. How to reference that I want to reference it only to those 3 elements? Maybe I need to have some List size of getChildren("CI") and to remove only when <=List Size. Is it good approach or what can you recommend me. Please once again sorry for additional questuion but you can see in my previous update what is my wish. THANK YOU!!! I marked your question as answered but JUST NEED HELP for this also – ja jaaaa May 07 '13 at 14:57
  • You can choose any number of ways to do it... for example, `List cis = incidentSet.getChildren("CI", erJdomNamespace); for (int i = cis.size() / 2 - 1; i >= 0; i--) { ((Element)cis.get(i)).removeChild("CIRELATION", erJdomNamespace); } ` – rolfl May 07 '13 at 15:05
  • It works thank you. But now I can not define to CLONE all children "CI". If I put incidentSet.addContent((Element)incidentSet.getChildren("CI", erJdomNamespace).clone()); I get the message : "The method clone() is undefined for the type List" – ja jaaaa May 07 '13 at 16:26
  • If I leave just incidentSet.getChild then it works but it will only CLONE me 1 CI and not 2 if I have 2 different CIs. Again really sorry for disturbing you. I am so close for the solution only problem is that I can not use getChild for CLONE. REMOVING works perfectly and there I can use removeChildren – ja jaaaa May 07 '13 at 16:29
  • I am sure this is the last thing if you can help me (thank you and please sorry for your time but we forgot that there are more then one CI which needs to be CLONED): How to clone CHILDREN CI- when there are more then 1 CI in default XML input. Clone method can not be used in this form :"incidentSet.addContent((Element)incidentSet.getChildren("CI", erJdomNamespace).clone())" – ja jaaaa May 07 '13 at 16:46
  • Hi, still can not CLONE multiple number of CIs. I tried this below but getting an error: List children=incidentSet.getChildren("CI", erJdomNamespace); Iterator li = children.iterator(); while(li.hasNext()) { incidentSet.addContent((Element)incidentSet.getChild("CI", erJdomNamespace).clone()); } – ja jaaaa May 07 '13 at 17:25
0

You have to add your repeating elements to a list, and then use addContent to add the list at the correct place in the structure.

    Document d = new Document();
    Element r = new Element("SyncMXAUTHCI");

    d.setRootElement(r);

    Element e = new Element("MXAUTHCISet");
    r.addContent(e);

    Element ae1 = new Element("CI");
    Element ae2 = new Element("CI");

    Element e2 = new Element("CINAME");
    e2.setText("COMPUTER68");
    ae1.setContent(e2);

    Element e3 = new Element("CINAME");
    e3.setText("COMPUTER68");
    ae2.setContent(e3);

    List l = new ArrayList();
    l.add(ae1);
    l.add(ae2);

    e.addContent(l);

    System.out.println(new XMLOutputter().outputString(d));
DaveH
  • 7,187
  • 5
  • 32
  • 53
  • Thank you for answer but this is not exactly what I meant: XML is coming from some external system and I must read how many CI elements does it have and than do duplicate that number of elements along with their values. In example I have 1 element but for example every time I could have on example 5 elements so I would like to duplicate them (to have them 10) with their values for CI – ja jaaaa May 07 '13 at 14:01
  • Can you please help me how to achieve this? THANK YOU!! So number of elements and their values is dynamic and every time different – ja jaaaa May 07 '13 at 14:02
  • This is really not solution because values are always dynamic also and number of elements. Could you please help me? Look in my update what I tried – ja jaaaa May 07 '13 at 14:09