0

I'm getting the following error,

java.io.IOException: Read error  
at java.io.FileInputStream.read(Native Method) at      
com.sun.org.apache.xerces.internal.impl.XMLEntityManager$RewindableInputStream.read(Unknown Source) 
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity  
(Unknown Source) at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion (Unknown Source)
       at    com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at   com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)  
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)  
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)  
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)  
at com.example.TestIntegrate.execute(TestIntegrate.java:71)  
at com.example.TestIntegrate.main(TestIntegrate.java:42)  

Here is my code:

    public class TestIntegrate {

    private Document doc = null;
    public static void main(String[] args) {
        FileInputStream fin;
        try {
            fin = new FileInputStream("C:/Users/xyz/workspace/TEST_2.xml");
            FileOutputStream fout = new FileOutputStream("C:/Users/xyz/workspace/OutputFile.xml");      
            TestIntegrate t = new TestIntegrate();
            t.execute(fin, fout);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public void execute(InputStream sourceFile, OutputStream targetFile) //throws StreamTransformationException
    {       
        BufferedReader reader;
        OutputStreamWriter writer;
        try{    

            // creating the parser object 
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            String line = "<Tax>";
            String line1 = "</Tax>";
            String currentLine;
            reader = new BufferedReader(new InputStreamReader(sourceFile));
            writer =new OutputStreamWriter(targetFile);

            dbFactory.setNamespaceAware(true);
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            while ( (currentLine = reader.readLine() ) != null){
                  String trimmedLine = currentLine.trim();
                  if(trimmedLine.equals(line) || trimmedLine.equals(line1) ) continue;
                  writer.write(currentLine + System.getProperty("line.separator"));
            }
            reader.close();
            writer.close();
            doc = dBuilder.parse(sourceFile);
            writeOutputfile(doc,targetFile);   
        } catch (Exception e) { 
            e.printStackTrace();    
        }   
    }
    private void writeOutputfile(Document doc,OutputStream targetFile) { 
            try {

                TransformerFactory transformFactory = TransformerFactory.newInstance();
                DOMSource source = new DOMSource(doc);
                Transformer transformer;
                transformer = transformFactory.newTransformer();
                Writer outWriter = new StringWriter();   
                StreamResult result = new StreamResult(targetFile);   
                transformer.transform(source,result);
            }
                 catch (TransformerException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
            }
    }

}

The process I have to do is:

1) reading the file from the source location.. ( here I am using main() just for testing purpose)

2) deleting the <Tax> and </Tax> nodes in the source file.

3) writng the file to target location.

XML FIle:

<!-- language: lang-xml -->

<?xml version="1.0" encoding="UTF-8"?>
<School>
    <SSLC>
        <name />
        <rollno />
    </SSLC>
    <Tax>
        <first_pu>
            <name />
            <rollno />
        </first_pu>
        <second_pu>
            <name />
            <rollno />
        </second_pu>
    </Tax>
    <Tax>
        <first_pu>
            <name />
            <rollno />
        </first_pu>
        <second_pu>
            <name />
            <rollno />
        </second_pu>
    </Tax>
    <Tax>
        <first_pu>
            <name />
            <rollno />
        </first_pu>
        <second_pu>
            <name />
            <rollno />
        </second_pu>
    </Tax>
</School>

please tell me the way to resolve this issue..

Thanks in advance..

5
  • Add the xml file in question. Commented Apr 13, 2015 at 7:33
  • Are you sure you have read access to file C:/Users/xyz/workspace/TEST_2.xml? Commented Apr 13, 2015 at 7:35
  • @SpaceTrucker - Yes I have access .. I have changed my system name to xyz Commented Apr 13, 2015 at 7:37
  • @Saint- Xml file added.. Commented Apr 13, 2015 at 7:38
  • Normally that would mean a disk error. You can't cope with those: you have to bail out. Commented Apr 13, 2015 at 9:41

2 Answers 2

2

UPDATED According to the new requirement:

You need to parse your XML document and get all those "Tax" tags. Then you need to collect their child elements and append them to the Tax' parent. Then, delete the Tax tag. This should look like the following (tested with your given document):

    public static void execute(InputStream in, OutputStream out) {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    Document doc = null;
    try {
        doc = factory.newDocumentBuilder().parse(in);
    } catch (SAXException | IOException | ParserConfigurationException e) {
        e.printStackTrace();
    }
    NodeList nodes = doc.getElementsByTagName("Tax");
    List<Node> nodesToRemove = new LinkedList<>();
    for (int i = 0; i < nodes.getLength(); i++) {
        Node node = nodes.item(i);
        nodesToRemove.add(node);

        List<Node> nodesToMove = new LinkedList<>();
        for (int j = 0; j < node.getChildNodes().getLength(); j++) {
            nodesToMove.add(node.getChildNodes().item(j));
        }

        for (Node childNode : nodesToMove) {
            node.removeChild(childNode);
            node.getParentNode().appendChild(childNode);
        }
    }

    for (Node n : nodesToRemove) {
        n.getParentNode().removeChild(n);
    }

    doc.normalize();

    Transformer tf = null;
    try {
        tf = TransformerFactory.newInstance().newTransformer();
    } catch (TransformerConfigurationException | TransformerFactoryConfigurationError e) {
        e.printStackTrace();
    }
    tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
    tf.setOutputProperty(OutputKeys.INDENT, "yes");
    tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
    try {
        tf.transform(new DOMSource(doc), new StreamResult(out));
    } catch (TransformerException e) {
        e.printStackTrace();
    }
}

You only need to put the <?xml ... ?> at the beginning of the input XML document. Otherwise you will get an Error: The processing instruction target matching “[xX][mM][lL]” is not allowed.


OLD:

The BufferedReader that is taking your InputStream in execute method is the problem, when you're closing it (lines 69,70).

Do not call close() on the BufferedReader, because it will close all system handles and files underneath it (see Javadoc for BufferedReader close() method).

Same applies for the OutputStreamWriter.

Instead of reader.close() you should call reader.reset(). This is because you already read the file and there is an internal cursor which points to the last read location and will you give you the next following data upon new read requests and moves itself forwards.

Sign up to request clarification or add additional context in comments.

8 Comments

@Ischuetze - Thanks.. If buffered reader is not closed I am getting [Fatal Error] :1:1: Premature end of file. org.xml.sax.SAXParseException: Premature end of file.
Sorry, forget to say that you should call reader.reset() instead of just closing it.
@JonasCz - Thanks.. If buffered reader is not closed I am getting [Fatal Error] :1:1: Premature end of file. org.xml.sax.SAXParseException: Premature end of file.
@Ischuetze -- thanks.. added reader.reset(); getting java.io.IOException: Stream not marked error..
According to the Javadoc you need to call reader.mark(0) before you are calling reader.reset(). I would suggest you to try @JanTheGrun 's approach.
|
0

You don't need the writeOutputfile method as you are already writing the new XML. Just remove the method and update your execute method like this:

public void execute(InputStream sourceFile, OutputStream targetFile) //throws StreamTransformationException
{       
    BufferedReader reader;
    OutputStreamWriter writer;
    try{    

        // creating the parser object 
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        String line = "<Tax>";
        String line1 = "</Tax>";
        String currentLine;
        reader = new BufferedReader(new InputStreamReader(sourceFile));
        writer =new OutputStreamWriter(targetFile);

        dbFactory.setNamespaceAware(true);
        while ( (currentLine = reader.readLine() ) != null){
              String trimmedLine = currentLine.trim();
              if(trimmedLine.equals(line) || trimmedLine.equals(line1) ) continue;
              writer.write(currentLine + System.getProperty("line.separator"));
        }

        reader.close();
        writer.close();
    } catch (Exception e) { 
        e.printStackTrace();    
    }   
}

EDIT: You can also parse the source file with the DOM parser, manipulate the DOM and write it back to a new file:

public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, TransformerException {
    try { 
        TestIntegrate t = new TestIntegrate();
        t.execute("C:/Users/xyz/workspace/TEST_2.xml", "C:/Users/xyz/workspace/OutputFile.xml");
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}


public void execute(String sourceFile, String targetFile) throws ParserConfigurationException, SAXException, IOException, TransformerException
{
    //Parse the source xml file
    File source = new File(sourceFile);
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    Document doc = dBuilder.parse(source);
    doc.getDocumentElement().normalize();

    NodeList taxNodes = doc.getElementsByTagName("Tax");

    //Loop through tax nodes and move inner nodes => start at the end as we remove the tax nodes afterwards
    for(int i = taxNodes.getLength() - 1; i > -1; i--)
    {
        Element taxNode = (Element) taxNodes.item(i);
        Node parent = taxNode.getParentNode();

        while (taxNode.hasChildNodes()) 
        {
            parent.insertBefore(taxNode.getFirstChild(), taxNode);
        }

        taxNodes.item(i).getParentNode().removeChild(taxNodes.item(i));
    }

    TransformerFactory transformerFactory = TransformerFactory.newInstance();
    Transformer transformer = transformerFactory.newTransformer();
    DOMSource domSource = new DOMSource(doc);
    StreamResult result = new StreamResult(new File(targetFile));
    transformer.transform(domSource, result);

}

http://www.java2s.com/Tutorial/Java/0440__XML/Moveallchildrenoftheelementinfrontoftheelement.htm

http://www.mkyong.com/java/how-to-read-xml-file-in-java-dom-parser/

EDIT2: Using InputStream and OutputStream (example) ...

public void execute(InputStream sourceFile, OutputStream targetFile) throws StreamTransformationException
{
    //Parse the source xml file
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = null;
    try
    {
        dBuilder = dbFactory.newDocumentBuilder();
    } 
    catch (ParserConfigurationException e)
    {
        throw new StreamTransformationException(e);
    }
    Document doc = null;
    try
    {
        doc = dBuilder.parse(sourceFile);
    }
    catch (SAXException e) 
    {
        throw new StreamTransformationException(e);
    } 
    catch (IOException e) 
    {
        throw new StreamTransformationException(e);
    }
    doc.getDocumentElement().normalize();

    NodeList taxNodes = doc.getElementsByTagName("Tax");

    //Loop through tax nodes and move inner nodes => start at the end as we remove the tax nodes afterwards
    for(int i = taxNodes.getLength() - 1; i > -1; i--)
    {
        Element taxNode = (Element) taxNodes.item(i);
        Node parent = taxNode.getParentNode();

        while (taxNode.hasChildNodes()) 
        {
            parent.insertBefore(taxNode.getFirstChild(), taxNode);
        }

        taxNodes.item(i).getParentNode().removeChild(taxNodes.item(i));
    }

    TransformerFactory transformerFactory = TransformerFactory.newInstance();
    Transformer transformer = null;
    try
    {
        transformer = transformerFactory.newTransformer();
    }
    catch (TransformerConfigurationException e)
    {
        throw new StreamTransformationException(e);
    }
    DOMSource domSource = new DOMSource(doc);
    StreamResult result = new StreamResult(targetFile);
    try
    {
        transformer.transform(domSource, result);
    } 
    catch (TransformerException e)
    {
        throw new StreamTransformationException(e);
    }

}

4 Comments

thanks.. I am working in SAP Pi- the purpose of PI is to read the XML file and generate XML file in turn sending it to the target.. Now the requirement is to generate XML file using DOM parser..( by truncating nodes).. or do I have to make anymore changes..
Thanks a lot.. Its working :) You made my day.. I wanted to resolve this issue by EOD ..
-- Done:) one more small doubt.. public void execute(String sourceFile, String targetFile) will this prototype reads the file from source location.. I am using main() just for testing purpose. I will comment main() while importing to PI. In PI the file is placed in some third party folder. I had previous implementation, there they have used.... public void execute(InputStream sourceFile, OutputStream targetFile) throws StreamTransformationException .. How does this impact..
I don't know how PI works, but please see my EDIT2 as an example: You can easily convert the parameters to InputStream and OutputStream. Also you can wrap the Exceptions in a StreamTransformationException, when you use try-catch blocks - so you don't get problems with the interface. But this is just an example. You'll have to find out what really makes sense. You could also throw a RuntimeException. But I don't know the context, so I don't know what should happen in case of an Exception ;-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.