From: Adam C. <Ada...@cn...> - 2008-03-18 00:04:17
|
Insert child into an empty node? (New) By: Adam Chang (adamcchang) - 2008-03-15 01:01 I saw there is a post in help section about inserting a child into an empty node. (e.g., insert <b></b> into <a></a> so the expected result is <a><b></b></a>) You suggested using the following code to do the job, but nav.getText() always returned -1 when there is no child existed. int i; while ((i = ap.evalXPath()) != -1) { // What should I be passing to updateToken()? i = nav.getText(); if (i!=-1) modifier.updateToken(i, xml); } ap.resetXPath(); Is there any way to insert a child into an empty node? Thanks. RE: Insert child into an empty node? (New) By: jimmy zhang (jzhang2004Project Admin) - 2008-03-15 13:01 It works for me...make sure you get the latest version (2.3) test.xml <a><b></b></a> new.xml <a><b>hello world!!</b></a> test.java import com.ximpleware.*; public class test { public static void main(String[] s) throws Exception{ VTDGen vg = new VTDGen(); if (vg.parseFile("test.xml",false)){ VTDNav vn = vg.getNav(); XMLModifier xm = new XMLModifier(vn); vn.toElement(VTDNav.FC); int i=vn.getText(); System.out.println(" the value of i is "+i); if (i!=-1){ xm.updateToken(i," hello world !!!".getBytes()); } xm.output("new.xml"); } } } RE: Insert child into an empty node? (New) By: Adam Chang (adamcchang) - 2008-03-16 00:37 Thanks for the quick reply, Jimmy. However, my xml is complex type unfortunately, which is not supported in getText(). Is there any way to move the cursor to the place so that I can insert an new child for the complex type parent? Thanks. RE: Insert child into an empty node? (New) By: jimmy zhang (jzhang2004Project Admin) - 2008-03-16 11:04 I may have to look at an example of your XML to make further suggestions... basically, you can insert an array of bytes at any offset location... or replace an array of bytes with somethng else ... so it is more or less choosing one of the member methods, there could be more than one way of doing it... RE: Insert child into an empty node? (New) By: Adam Chang (adamcchang) - 2008-03-16 19:56 original xml: <nodeA name="A" id="33"></nodeA> I need to insert a text (e.g., "nodeA text content") or another node in text format (e.g., "<nodeAChild1 name="child1" id="34"></nodeAChild1>" into the text area of nodeA. expected xml: text case: <nodeA name="A" id="33">nodeA text content</nodeA> child node case: <nodeA name="A" id="33"><nodeAChild1 name="child1" id="34"></nodeAChild1></nodeA> Please note in the original xml, nodeA may have 0 - many attributes so there is no way for me to calculate the exact offset. I am thinking to calculate back from its next sibling / or end of the parent position if there is no sibling. I just wonder if you have any quicker and more straight way to do this. Please let me know what you think. Thanks a lot. RE: Insert child into an empty node? (New) By: jimmy zhang (jzhang2004Project Admin) - 2008-03-16 22:08 Adam, <nodeA name="A" id="33"></nodeA> has a zero widith text node that you can use as the basis for update... the code snippet for inserting text would be something like: int i = vn.getText(); if (i!=-1){ xm.updateToken(i, "node A text content".getBytes()); } xm.output("new.xml"); the code snippet for inserting an element node would be like: int i= vn.getText(); if (i!=-1){ xm.updateToken(i, "<nodeAChild1 name="child1" id="34"></nodeAChild1>".getBytes()); } xm.output("new.xml"); RE: Insert child into an empty node? (New) By: Adam Chang (adamcchang) - 2008-03-17 00:03 Thanks again for the quick reply, Jimmy. However, getting to the index of the position after <nodeA name="A" id="33"> is the problem. If nodeA is not a complex type (e.g., <nodeA></nodeA>) then getText() works just fine as you described in the previous message. However, <nodeA name="A" id="33"></nodeA> is a complex type, and getText() will always return -1. Is there any current api that can get me to the index after <nodeA name="A" id="33">? Thanks. Here is the example you showed me earlier, and if I make node <b> in test.xml a complex type, then getText() returns -1. test.xml <a><b c="1"></b></a> test.java import com.ximpleware.*; public class test { public static void main(String[] s) throws Exception{ VTDGen vg = new VTDGen(); if (vg.parseFile("test.xml",false)){ VTDNav vn = vg.getNav(); XMLModifier xm = new XMLModifier(vn); vn.toElement(VTDNav.FC); int i=vn.getText(); System.out.println(" the value of i is "+i); if (i!=-1){ xm.updateToken(i," hello world !!!".getBytes()); } xm.output("new.xml"); } } } RE: Insert child into an empty node? (New) By: jimmy zhang (jzhang2004Project Admin) - 2008-03-17 13:03 I guess your situation is that you don't know whether is a text value or a child element.. am I right on this? RE: Insert child into an empty node? (New) By: Adam Chang (adamcchang) - 2008-03-17 13:07 My question is, how do I get the index of the # position in <a id="3>#</a>. RE: Insert child into an empty node? (New) By: jimmy zhang (jzhang2004Project Admin) - 2008-03-17 13:30 There is no direct support for that at the current version (2.3) the workaround does exist... at node a, you try to get the text node if it is not -1 you update the node value using updatetoken if it is -1, then you navigate to the first child node, call insertBeforeElement()... that would be my answer for now ... RE: Insert child into an empty node? (New) By: Adam Chang (adamcchang) - 2008-03-17 14:37 What if there is no child node at all? Say if the xml is <a id="3">#<a><b id="4"><b>, and I want to insert "<a1>a1</a1>" into the # position. (Expected xml: <a id="3"><a1>a1</a1><a><b id="4"><b>) The only way I can think of is navigate to node b, and back track to # position. How do you think? RE: Insert child into an empty node? (New) By: jimmy zhang (jzhang2004Project Admin) - 2008-03-17 15:16 the only case I can think is <a id="3"/>... which has no text, no child node... everything else... it either has a text node (albeit zero width) or child nodes... For <a id="3">#<a><b id="4"><b>, # is a text node... you can getText() than call updateToken ... does it make sense? RE: Insert child into an empty node? (New) By: Adam Chang (adamcchang) - 2008-03-17 15:45 Sorry for the mis-leading, # is just a marker I use to show you the place I want to insert into. Yes, your case is correct. xml is <a id="3" /><b id="4" /b>, and I want to insert <a1>a1</a1> as child of <a id="3" /> so the output xml is <a id="3"><a1>a1</a1><a><b id="4" />. You have any good way to do it? Thanks. RE: Insert child into an empty node? (New) By: jimmy zhang (jzhang2004Project Admin) - 2008-03-17 16:11 Yes, there are ways to do that... remember that update is the combination of a delete and an insert from <a id="3" /><b id="4" /b> to <a id="3"> a </a><b id="4"/> u basically *navigate to node <a> *insert before element a "<a id="3"> a </a>" *then remove "a" from <a id="3"> a </a><b id="4"/> to <a id="3"> a </a> <b id="4"> b <b/> you basically *navigate to <b> *insert before node b "<b id="4"> b <b/>" * then remove the entire element b Does it make sense? Cheers, Jim RE: Insert child into an empty node? (New) By: Adam Chang (adamcchang) - 2008-03-17 15:47 Some typo. input xml: <a id="3" /><b id="4" /> outpu xml: <a id="3"><a1>a1</a1></a><b id="4" /> RE: Insert child into an empty node? (New) By: jimmy zhang (jzhang2004Project Admin) - 2008-03-17 16:15 input xml: <a id="3" /><b id="4" /> output xml: <a id="3"><a1>a1</a1></a><b id="4" /> u basically do the following 1. navigate to <a> as in <a id="3"/> 2. insert before element <a id="3"><a1>a1</a1></a> 3. remove node a RE: Insert child into an empty node? (New) By: jimmy zhang (jzhang2004Project Admin) - 2008-03-17 16:40 Also if you join the vtd-xml-users mailing list, I would be able to check more often ... RE: Insert child into an empty node? (New) By: Adam Chang (adamcchang) - 2008-03-17 16:50 Sorry Jim, I am not too clear on this. All I know is what I need to insert. (In this case, is text "<a1>a1</a1>"). And I know my cursor is pointing to the parent (in this case, nav is at the head of <a id="3" />..., but I don't know what is the content of node a, which could be <a />, <a id="3" />, or <a id="3"><a2>a2</a2></a>...etc, and I don't know the expected output either). And I need to have the new xml which node a has the text "<a1>a1</a1>" to be the last child. (case <a />, output xml is <a><a1>a1</a1></a>, case <a id="3" />, output xml is <a id="3"><a1>a1</a1></a>, case <a id="3"><a2>a2</a2></a>, output xml is <a id="3"><a2>a2</a2><a1>a1</a1></a>). Your suggestion sounds more like I already know the expected output, but in fact I don't. So I can't just insert the expected output right before the element a and then remove a later. Is there any other way to do it? Thanks for your help and time, I really appreciate it. :) |