How do I handle error when parsing an XML file using SAX?

The ErrorHandler interface implemented by the org.xml.sax.helpers.DefaultHandler class provides some methods for error handling mechanism in SAX parsing. The methods are warning(), error(), and fatalError().

package org.kodejava.xml;

import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.InputStream;

public class SAXErrorHandlerDemo {
    public static void main(String[] args) throws Exception {
        SAXErrorHandlerDemo demo = new SAXErrorHandlerDemo();
        demo.run();
    }

    public void run() throws Exception {
        // Creates the SAXParserFactory and SAXParser instance.
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser = factory.newSAXParser();

        // Parse the error.xml file using MySAXHandler as the 
        // DefaultHandler implementation.
        InputStream is = getClass().getResourceAsStream("/error.xml");
        DefaultHandler handler = new MySAXHandler();
        parser.parse(is, handler);
    }

    // Override the error handling methods defined by the ErrorHandler
    // interface. This method will handler exceptions thrown by the
    // parsing process.
    static class MySAXHandler extends DefaultHandler {
        @Override
        public void warning(SAXParseException e) throws SAXException {
            System.out.println("warning   : " + e.getMessage());
        }

        @Override
        public void error(SAXParseException e) throws SAXException {
            System.out.println("error     : " + e.getMessage());
        }

        @Override
        public void fatalError(SAXParseException e) throws SAXException {
            System.out.println("fatalError: " + e.getMessage());
        }
    }
}

How do I build object from XML file using SAX?

This example will show you how to parse an XML file using SAX parser and build an object graph from the parsed XML. We will read the records.xml file that contains some recording information and create the Record object from it.

The DefaultHandler in this example created as an anonymous class. We override some method related to the ContentHandler interface such as the startElement, endElement and characters methods.

package org.kodejava.xml;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import org.kodejava.xml.support.Record;

public class SAXDataDemo {
    // List of our records.
    private final List<Record> records = new ArrayList<>();

    // Stacks for storing the elements and objects.
    private final Stack<String> elements = new Stack<>();
    private final Stack<Record> objects = new Stack<>();

    public static void main(String[] args) {
        SAXDataDemo demo = new SAXDataDemo();
        demo.run();
    }

    private void run() {
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();

            String filename = "/records.xml";
            InputStream is = getClass().getResourceAsStream(filename);

            parser.parse(is, new DefaultHandler() {
                @Override
                public void startElement(String uri, String localName, String qName,
                                         Attributes attributes) throws SAXException {
                    elements.push(qName);
                    if ("record".equals(qName)) {
                        Record record = new Record();
                        objects.push(record);
                        records.add(record);
                    }
                }

                @Override
                public void endElement(String uri, String localName,
                                       String qName) throws SAXException {
                    elements.pop();
                }

                @Override
                public void characters(char[] ch, int start, int length)
                        throws SAXException {

                    String value = new String(ch, start, length);
                    if (value.length() == 0) {
                        return;
                    }

                    if ("title".equals(currentElement())) {
                        Record record = objects.peek();
                        record.setTitle(value);
                    } else if ("artist".equals(currentElement())) {
                        Record record = objects.peek();
                        record.setArtist(value);
                    } else if ("genre".equals(currentElement())) {
                        Record record = objects.peek();
                        record.setGenre(value);
                    } else if ("year".equals(currentElement())) {
                        Record record = objects.peek();
                        record.setYear(Integer.parseInt(value));
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }

        for (Record record : records) {
            System.out.println("record = " + record);
        }
    }

    private String currentElement() {
        return elements.peek();
    }
}

The Record class.

package org.kodejava.xml.support;

public class Record {
    private String title;
    private String artist;
    private String genre;
    private int year;

    public Record() {
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setArtist(String artist) {
        this.artist = artist;
    }

    public void setGenre(String genre) {
        this.genre = genre;
    }

    public void setYear(int year) {
        this.year = year;
    }

    @Override
    public String toString() {
        return "Record{" +
                "title='" + title + "'\n" +
                ", artist='" + artist + "'\n" +
                ", genre='" + genre + "'\n" +
                ", year=" + year +
                '}';
    }
}

The following XML is the content of our records.xml file.

<?xml version="1.0"?>
<root>
    <records>
        <record>
            <title>Brand New Eyes</title>
            <artist>Paramore</artist>
            <genre>Punk Rock</genre>
            <year>2011</year>
        </record>
        <record>
            <title>Rock Beatles</title>
            <artist>Various Artist</artist>
            <genre>Rock</genre>
            <year>2010</year>
        </record>
    </records>
</root>

When we run this example will get the following output:

record = Record{title='Brand New Eyes'
, artist='Paramore'
, genre='Punk Rock'
, year=2011}
record = Record{title='Rock Beatles'
, artist='Various Artist'
, genre='Rock'
, year=2010}

How do I create a java.io.File object from URL?

The code snippet below uses the FileUtils.toFile(URL) method that can be found in the Apache Commons IO library to convert a URL into a File. The url protocol should be file or else null will be returned.

package org.kodejava.commons.io;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

public class URLToFileObject {
    public static void main(String[] args) throws Exception {
        // FileUtils.toFile(URL url) convert from URL the File.
        String data = FileUtils.readFileToString(Objects.requireNonNull(
                        FileUtils.toFile(URLToFileObject.class.getResource("/data.txt"))),
                StandardCharsets.UTF_8);
        System.out.println("data = " + data);

        // Creates a URL with file protocol and convert it into File object.
        File file = FileUtils.toFile(URI.create("file:///D:/data.txt").toURL());
        data = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
        System.out.println("data = " + data);
    }
}

Maven Dependencies

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.16.1</version>
</dependency>

Maven Central

How do I parse an XML file using SAX?

This example show you how to read / parse an xml file using the SAX (Simple API for XML) parser. In the main class (SAXDemo) we create the instance of SAXParserFactory and the SAXParser. The SAXParser.parse() method will parse the given InputStream and handle the xml document using the SAXHandler class that we created.

package org.kodejava.xml;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.InputStream;

public class SAXDemo {
    public static void main(String[] args) throws Exception {
        // Creates a new instance of SAXParserFactory that in turn
        // creates a SAXParser.
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser = factory.newSAXParser();

        // The handler that will listen to the SAX event during
        // the xml traversal.
        SAXHandler handler = new SAXHandler();
        InputStream data = SAXDemo.class.getResourceAsStream("/person.xml");
        parser.parse(data, handler);
    }
}

The SAXHandler class extended from the org.xml.sax.helpers.DefaultHandler class. The handler will listen to the event triggered by the SAXParser. This handler methods is defined by the interfaces such as the ContentHandler, ErrorHandler, DTDHandler, and EntityResolver.

For example to read the content of the XML file there are methods to listen to events such as startDocument, endDocument, startElement, endElement, etc, which defined by the ContentHandler interface.

package org.kodejava.xml;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SAXHandler extends DefaultHandler {
    @Override
    public void startDocument() throws SAXException {
        System.out.println("startDocument");
    }

    @Override
    public void endDocument() throws SAXException {
        System.out.println("endDocument");
    }

    @Override
    public void startElement(String uri, String localName,
                             String qName, Attributes attributes)
            throws SAXException {
        System.out.println("startElement: " + qName);
    }

    @Override
    public void endElement(String uri, String localName,
                           String qName) throws SAXException {
        System.out.println("endElement");
    }

    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        System.out.println("characters  : " + new String(ch, start, length));
    }
}

Here an example of the xml file will be read by our program:

<root>
    <persons>
        <person>
            <name>Foo</name>
        </person>
        <person>
            <name>Bar</name>
        </person>
    </persons>
</root>

Our program will print the following output:

startDocument
startElement: root
characters  : 

startElement: persons
characters  : 

startElement: person
characters  : 

startElement: name
characters  : Foo
endElement
characters  : 

endElement
characters  : 

startElement: person
characters  : 

startElement: name
characters  : Bar
endElement
characters  : 

endElement
characters  : 

endElement
characters  : 

endElement
endDocument

How do I create super / subscript in iText?

The following example you’ll see how to create a superscript and subscript text in the pdf document using iText. We can use the Chunk‘s class method called setTextRise(). A positive value will create a superscript text while a negative value will create a subscript text.

package org.kodejava.itextpdf;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class SuperSubscriptDemo {
    public static void main(String[] args) {
        Document doc = new Document();
        try {
            PdfWriter.getInstance(doc, new FileOutputStream("SuperSubscript.pdf"));
            doc.open();

            Font small = FontFactory.getFont(FontFactory.HELVETICA, 5, Font.ITALIC);

            // Add some chunks into the doc object.
            doc.add(new Chunk("The quick brown  "));

            Chunk superscript = new Chunk("fox ");
            superscript.setTextRise(5f);
            superscript.setFont(small);
            doc.add(superscript);

            doc.add(new Chunk("jumps over the lazy "));

            Chunk subscript = new Chunk("dog");
            subscript.setTextRise(-5f);
            subscript.setFont(small);
            doc.add(subscript);
        } catch (DocumentException | FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            doc.close();
        }
    }
}

Maven Dependencies

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13.3</version>
</dependency>

Maven Central

How do I create an underlined or strike through chunk in iText?

You can use the Chunk‘s setUnderline(float thickness, float yPosition) method to add underline or strike through to a chunk. A negative value to the yPosition create an underline while a positive value will produce a strike through.

package org.kodejava.itextpdf;

import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class UnderlineStrikeThroughDemo {
    public static void main(String[] args) {
        Document doc = new Document();
        try {
            PdfWriter.getInstance(doc, new FileOutputStream("UnderStrike.pdf"));
            doc.open();

            // Creates a chunk with an underline with 0.1 thickness
            Chunk underline = new Chunk("The quick brown fox ");
            underline.setUnderline(0.1f, -1f);
            doc.add(underline);

            // Creates a strike through chunk with 1 thickness
            Chunk strike = new Chunk("jumps over the lazy dog.");
            strike.setUnderline(1f, 3f);
            doc.add(strike);
        } catch (DocumentException | FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            doc.close();
        }
    }
}

Maven Dependencies

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13.3</version>
</dependency>

Maven Central

How do I define a font for text object in iText?

We can set font style for text object such as Chunk, Phrase, Paragraph, etc. using the com.itextpdf.text.Font class. We can define the font face, size, style and its color using this class.

package org.kodejava.itextpdf;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class FontDemo {
    public static void main(String[] args) {
        Document doc = new Document();
        try {
            PdfWriter.getInstance(doc, new FileOutputStream("FontDemo.pdf"));
            doc.open();

            // Creates some fonts
            Font largeBold = new Font(Font.FontFamily.COURIER, 32,
                    Font.BOLD);
            Font smallItalic = new Font(Font.FontFamily.HELVETICA, 10,
                    Font.ITALIC);
            Font redFont = new Font(Font.FontFamily.TIMES_ROMAN, 12,
                    Font.ITALIC | Font.UNDERLINE, BaseColor.RED);

            // Creates chunk, phrase and paragraph with font
            // information.
            Chunk chunk = new Chunk("Hello World", largeBold);
            Phrase phrase =
                    new Phrase("The quick brown fox ", smallItalic);
            Paragraph paragraph =
                    new Paragraph("jumps over the lazy dog", redFont);

            doc.add(chunk);
            doc.add(phrase);
            doc.add(paragraph);
        } catch (DocumentException | FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            doc.close();
        }
    }
}

Maven Dependencies

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13.3</version>
</dependency>

Maven Central

How do I rotate image in iText PDF document?

You can rotate images in the iText pdf document using the setRotation(final float r) or the setRotationDegrees(final float deg) methods of the com.itextpdf.text.Image class. This method sets the rotation in radian and in degree respectively. Let’s see an example below:

package org.kodejava.itextpdf;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.FileOutputStream;
import java.io.IOException;

public class ImageRotateDemo {
    public static void main(String[] args) {
        Document doc = new Document();
        try {
            PdfWriter.getInstance(doc, new FileOutputStream("ImageRotation.pdf"));
            doc.open();

            // Rotate image in radian using the setRotation method.
            String filename = "kodejava-itextpdf/src/main/resources/java.png";
            Image image = Image.getInstance(filename);
            image.setRotation(90f);
            doc.add(image);

            // The following line to prevent the "Server returned
            // HTTP response code: 403" error.
            System.setProperty("http.agent", "Chrome");

            // Rotate image in degree using the setRotationDegree method
            String url = "https://kodejava.org/wp-content/uploads/2017/01/kodejava.png";
            image = Image.getInstance(url);
            image.setRotationDegrees(90);
            doc.add(image);
        } catch (DocumentException | IOException e) {
            e.printStackTrace();
        } finally {
            doc.close();
        }
    }
}

Maven Dependencies

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13.3</version>
</dependency>

Maven Central

How do I scale an image in PDF document using iText?

The com.itextpdf.text.Image class represent an image of a graphic element such as JPEG, PNG or GIF that can be inserted into a PDF document. There are some methods of the com.itextpdf.text.Image class that can be used to scale the image. These methods include the following: scaleAbsolute(), scaleAbsoluteHeight(), scaleAbsoluteWidth(), scalePercent() and scaleToFit().

These are signatures of those APIs:

  • scaleAbsolute(float newWidth, fload newHeight) – Scales the image to an absolute width and an absolute height.
  • scaleAbsoluteHeight(float newHeight) – Scales the image to an absolute height.
  • scaleAbsoluteWidht(float newWidth) – Scales the image to an absolute width.
  • scalePercent(float percent) – Scales the image to a certain percentage.
  • scalePercent(float percentX, float percentY) – Scales the image to a certain percentage of width and height.
  • scaleToFit(float fitWidth, float fitHeight) – Scales the image to fit a certain width and height.

Here is a code snippet that shows how to use the scaleAbsolute(), scalePercent() and scaleToFit() methods.

package org.kodejava.itextpdf;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.FileOutputStream;
import java.io.IOException;

public class ImageScalingDemo {
    public static void main(String[] args) {
        Document doc = new Document();
        try {
            PdfWriter.getInstance(doc, new FileOutputStream("ImageScaling.pdf"));
            doc.open();

            // Scale the image to an absolute width and an absolute
            // height
            String filename = "kodejava-itextpdf/src/main/resources/java.png";
            Image image = Image.getInstance(filename);
            image.scaleAbsolute(200f, 200f);
            doc.add(image);

            // The following line to prevent the "Server returned
            // HTTP response code: 403" error.
            System.setProperty("http.agent", "Chrome");

            // Scale the image to a certain percentage
            String url = "https://kodejava.org/wp-content/uploads/2017/01/kodejava.png";
            image = Image.getInstance(url);
            image.scalePercent(200f);
            doc.add(image);

            // Scales the image so that it fits a certain width and
            // height
            image = Image.getInstance(url);
            image.scaleToFit(100f, 200f);
            doc.add(image);
        } catch (DocumentException | IOException e) {
            e.printStackTrace();
        } finally {
            doc.close();
        }
    }
}

Maven Dependencies

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13.3</version>
</dependency>

Maven Central

How do I set the absolute position of an image in iText?

To set the absolute position of an image you can use the setAbsolutePosition() method. This method takes two parameters the X and Y coordinate where the image will be placed. In the pdf document the 0, 0 coordinate is located at the left bottom corner of the document. Let’s see an example below:

package org.kodejava.itextpdf;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.FileOutputStream;
import java.io.IOException;

public class ImageAbsolutePosition {
    public static void main(String[] args) {
        Document doc = new Document();
        try {
            PdfWriter.getInstance(doc, new FileOutputStream("ImageAbsolutePosition.pdf"));
            doc.open();

            // Sets the absolute position of the image.
            String filename = "kodejava-itextpdf/src/main/resources/java.png";
            Image image = Image.getInstance(filename);
            image.setAbsolutePosition(0f, 0f);
            doc.add(image);
        } catch (DocumentException | IOException e) {
            e.printStackTrace();
        } finally {
            doc.close();
        }
    }
}

Maven Dependencies

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13.3</version>
</dependency>

Maven Central