-1

The XML file I use is like this, pay attention that there are 4 'target' tag.

<?xml version="1.0" encoding="UTF-8" standalone="no"?><project basedir="." default="end" name="precompile">
<property name="charset" value="utf-8"/>

<target name="start">
</target>

<target depends="precompile-templates1,precompile-templates2" name="end">
    <echo>finish generating precompiled templates</echo>
</target>



<target name="precompile-templates1">
      <property name="outputJS1" value="jsp/jsp_2/js/templates.js"/>
      <property name="templatesPath1" value="jsp/jsp_2/js/tmpl"/>

      <java dir="${basedir}" failonerror="true" fork="true" jar="lib/js.jar">
        <arg value="otherFiles/lib/rhino-handlebars-compiler.js"/>
        <arg value="--handlebars"/>
        <arg value="otherFiles/third-party/handlebars-v1.3.0.js"/>
        <arg value="--templates"/>
        <arg value="${templatesPath1}"/>
        <arg value="--output"/>
        <arg value="${outputJS1}"/>
      </java>
      <echo>Template Precompiled to web/js/compiled-templates.js</echo>
        <echo> is now ready to compress....</echo>
</target>

<target name="precompile-templates2">
        <property name="outputJS2" value="jsp/jsp_3/js/templates.js"/>
        <property name="templatesPath2" value="jsp/jsp_3/js/tmpl"/>

        <java dir="${basedir}" failonerror="true" fork="true" jar="lib/js.jar">
        <arg value="otherFiles/lib/rhino-handlebars-compiler.js"/>
        <arg value="--handlebars"/>
        <arg value="otherFiles/third-party/handlebars-v1.3.0.js"/>
        <arg value="--templates"/>
        <arg value="${templatesPath2}"/>
        <arg value="--output"/>
        <arg value="${outputJS2}"/>
      </java>
      <echo>Template Precompiled to web/js/compiled-templates.js</echo>
        <echo> is now ready to compress....</echo>
</target></project>

I want to keep the first 2 'target' node but remove the rest 2 nodes of 'target'. What should I do? I was trying to do something like this:

File fXmlFile = new File(subBuildFile);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder  dBuilder = dbFactory.newDocumentBuilder();
Document  doc = dBuilder.parse(fXmlFile);

Node s = doc.getElementsByTagName("target").item(1);

for(int i =2; i<doc.getElementsByTagName("target").getLength();i++){
    doc.getElementsByTagName("target").item(i).removeChild(doc.getElementsByTagName("target").item(i));
}

But there always is a similar error like this:

Exception in thread "main" org.w3c.dom.DOMException: NOT_FOUND_ERR: An attempt is made to reference a node in a context where it does not exist.
at com.sun.org.apache.xerces.internal.dom.ParentNode.internalRemoveChild(Unknown Source)
at com.sun.org.apache.xerces.internal.dom.ParentNode.removeChild(Unknown Source)
at xmlReader.Test.resetXML(Test.java:52)
at xmlReader.Test.main(Test.java:39)

Any suggestion?

Plus: Something weird when I use the following codes:

System.out.println("the number of target tag is "+doc.getElementsByTagName("target").getLength());

    for(int i =2; i<targets.getLength();i++){
        root.removeChild(targets.item(2));
        System.out.println(i);


    }

    System.out.println(doc.getElementsByTagName("target").getLength());

The XML I use is like this:

 <target name="start">
 </target>

<target depends="precompile-templates1,precompile-templates2" name="end">
    <echo>finish generating precompiled templates</echo>
</target>










<target id="2">
</target>
<target id="3">
</target>
<target id="4">
</target>

<target id="5">
</target>
<target id="6">
</target>

<target id="7">
</target>
<target id="8">
</target>
<target id="9">
</target>
<target id="10">
</target>
<target id="11">
</target>
<target id="12">
</target>
<target id="13">
</target>


















</project>

The output will like this:

the number of target tag is 8
2
3
4
5

And the final output XML is like this:

<target name="start">
</target>

<target depends="precompile-templates1,precompile-templates2" name="end">
    <echo>finish generating precompiled templates</echo>
</target>





















<target id="11">
</target>
<target id="12">
</target>
<target id="13">
</target>
</project>
diCoder
  • 181
  • 2
  • 3
  • 14

1 Answers1

2

The expression

doc.getElementsByTagName("target").item(i)

selects a <target> and you can't remove a <target> from it.

Element root = doc.getDocumentElement(); // should be <project>
NodeList targets = doc.getElementsByTagName("target");
root.removeChild( targets.item( 3 ) );
root.removeChild( targets.item( 2 ) );

A more general code that's not hardwired on 2 would be:

int toKeep = 2;
int toDelete = targets.getLength() - toKeep;
for(int i = 0; i < toDelete; i++){
root.removeChild(targets.item(toKeep));
}

Note that (in contrast to your code) the number of target elements to be deleted is computed up front. Limiting it with the changing length of the list create a strange effect.

laune
  • 31,114
  • 3
  • 29
  • 42
  • 1
    This fails because after item 2 was removed, there is only 3 elements. Then it should be twice `root.removeChild( targets.item( 2 ) );` – mpromonet Jul 28 '14 at 19:00
  • @mpromonet I wasn't sure whether the index in the extracted list would remain or not. Swapping the statements should avoid this issue. Thanks. – laune Jul 28 '14 at 19:07