© Jeff Friesen 2019
Jeff FriesenJava XML and JSONhttps://doi.org/10.1007/978-1-4842-4330-5_13

Answers to Exercises

Jeff Friesen1 
(1)
Dauphin, MB, Canada
 

Each of Chapters 1 through 12 closes with an “Exercises” section that tests your understanding of the chapter’s material. The answers to those exercises are presented in this appendix.

Chapter 1: Introducing XML

  1. 1.

    XML (eXtensible Markup Language) is a meta-language for defining vocabularies (custom markup languages), which is the key to XML’s importance and popularity.

     
  2. 2.

    The answer is true: XML and HTML are descendants of SGML.

     
  3. 3.

    XML provides the XML declaration, elements and attributes, character references and CDATA sections, namespaces, and comments and processing-instruction language features for use in defining custom markup languages.

     
  4. 4.

    The XML declaration is special markup that informs an XML parser that the document is XML.

     
  5. 5.

    The XML declaration’s three attributes are version, encoding, and standalone. The version attribute is nonoptional.

     
  6. 6.

    The answer is false: an element can consist of the empty-element tag, which is a standalone tag whose name ends with a forward slash (/), such as <break/>.

     
  7. 7.

    Following the XML declaration, an XML document is anchored in a root element.

     
  8. 8.

    Mixed content is a combination of child elements and content.

     
  9. 9.

    A character reference is a code that represents a character. The two kinds of character references are numeric character references (such as Σ) and character entity references (such as <).

     
  10. 10.

    A CDATA section is a section of literal HTML or XML markup and content surrounded by the <![CDATA[ prefix and the ]]> suffix. You would use a CDATA section when you have a large amount of HTML/XML text and don’t want to replace each literal < (start of tag) and & (start of entity) character with its < and & predefined character entity reference, which is a tedious and possibly error-prone undertaking—you might forget to replace one of these characters.

     
  11. 11.

    A namespace is a Uniform Resource Identifier-based container that helps differentiate XML vocabularies by providing a unique context for its contained identifiers.

     
  12. 12.

    A namespace prefix is an alias for a URI.

     
  13. 13.

    The answer is true: a tag’s attributes don’t need to be prefixed when those attributes belong to the element.

     
  14. 14.

    A comment is a character sequence beginning with <!-- and ending with -->. It can appear anywhere in an XML document except before the XML declaration, except within tags, and except within another comment.

     
  15. 15.

    A processing instruction is an instruction that’s made available to the application parsing the document. The instruction begins with <? and ends with ?>.

     
  16. 16.

    The rules that an XML document must follow to be considered well formed are as follows: all elements must either have start and end tags or consist of empty-element tags, tags must be nested correctly, all attribute values must be quoted, empty elements must be properly formatted, and you must be careful with case. Furthermore, XML parsers that are aware of namespaces enforce two additional rules: all element and attribute names must not include more than one colon character; and no entity names, processing-instruction targets, or notation names can contain colons.

     
  17. 17.

    For an XML document to be valid, the document must adhere to certain constraints. For example, one constraint might be that a specific element must always follow another specific element.

     
  18. 18.

    The two common grammar languages are Document Type Definition and XML Schema.

     
  19. 19.

    The general syntax for declaring an element in a DTD is <!ELEMENT name content-specifier>.

     
  20. 20.

    XML Schema lets you create complex types from simple types.

     
  21. 21.

    Listing A-1 presents the books.xml document file that was called for in Chapter 1.

     
<?xml version="1.0"?>
<books>
   <book isbn="0201548550" pubyear="1992">
      <title>
         Advanced C++
      </title>
      394211_2_En
         James O. Coplien
      </author>
      <publisher>
         Addison Wesley
      </publisher>
   </book>
   <book isbn="9781430210450" pubyear="2008">
      <title>
         Beginning Groovy and Grails
      </title>
      394211_2_En
         Christopher M. Judd
      </author>
      394211_2_En
         Joseph Faisal Nusairat
      </author>
      394211_2_En
         James Shingler
      </author>
      <publisher>
         Apress
      </publisher>
   </book>
   <book isbn="0201310058" pubyear="2001">
      <title>
         Effective Java
      </title>
      394211_2_En
         Joshua Bloch
      </author>
      <publisher>
         Addison Wesley
      </publisher>
   </book>
</books>
Listing A-1

A Document of Books

  1. 22.

    Listing A-2 presents the books.xml document file with an internal DTD that was called for in Chapter 1.

     
<?xml version="1.0"?>
<!DOCTYPE books [
   <!ELEMENT books (book+)>
   <!ELEMENT book (title, author+, publisher)>
   <!ELEMENT title (#PCDATA)>
   <!ELEMENT author (#PCDATA)>
   <!ELEMENT publisher (#PCDATA)>
   <!ATTLIST book isbn CDATA #REQUIRED>
   <!ATTLIST book pubyear CDATA #REQUIRED>
]>
<books>
   <book isbn="0201548550" pubyear="1992">
      <title>
         Advanced C++
      </title>
      394211_2_En
         James O. Coplien
      </author>
      <publisher>
         Addison Wesley
      </publisher>
   </book>
   <book isbn="9781430210450" pubyear="2008">
      <title>
         Beginning Groovy and Grails
      </title>
      394211_2_En
         Christopher M. Judd
      </author>
      394211_2_En
         Joseph Faisal Nusairat
      </author>
      394211_2_En
         James Shingler
      </author>
      <publisher>
         Apress
      </publisher>
   </book>
   <book isbn="0201310058" pubyear="2001">
      <title>
         Effective Java
      </title>
      394211_2_En
         Joshua Bloch
      </author>
      <publisher>
         Addison Wesley
      </publisher>
   </book>
</books>
Listing A-2

A DTD-Enabled Document of Books

Chapter 2: Parsing XML Documents with SAX

  1. 1.

    SAX is an event-based Java API for parsing an XML document sequentially from start to finish. As a SAX-oriented parser encounters an item from the document’s infoset, it makes this item available to an application as an event by calling one of the methods in one of the application’s handlers, which the application has previously registered with the parser. The application can then consume this event by processing the infoset item in some manner.

     
  2. 2.

    You obtain a SAX 2-based parser by obtaining a SAXParserFactory instance , then configuring this instance, then returning a SAXParser instance from the SAXParserFactory, and finally returning an XMLReader instance from the SAXParser.

     
  3. 3.

    The purpose of the XMLReader interface is to describe a SAX 2 parser. This interface makes available several methods for configuring the SAX 2 parser and parsing an XML document’s content.

     
  4. 4.

    You tell a SAX parser to perform validation by invoking XMLReader’s setFeature(String name, boolean value) method, passing " http://xml.org/sax/features/validation " to name and true to value.

     
  5. 5.

    The four kinds of SAX-oriented exceptions that can be thrown when working with SAX are SAXException, SAXNotRecognizedException, SAXNotSupportedException, and SAXParseException.

     
  6. 6.

    The interface that a handler class implements to respond to content-oriented events is ContentHandler.

     
  7. 7.

    The three other core interfaces that a handler class is likely to implement are DTDHandler, EntityResolver, and ErrorHandler.

     
  8. 8.

    Ignorable whitespace is whitespace located between tags where the DTD doesn’t allow mixed content.

     
  9. 9.

    The answer is false: void error(SAXParseException exception) is called only for recoverable errors.

     
  10. 10.

    The purpose of the DefaultHandler class is to serve as a convenience base class for SAX 2 applications. It provides default implementations for all of the callbacks in the four core SAX 2 handler interfaces: ContentHandler, DTDHandler, EntityResolver, and ErrorHandler.

     
  11. 11.

    An entity is aliased data. An entity resolver is an object that uses the public identifier to choose a different system identifier. Upon encountering an external entity, the parser calls the custom entity resolver to obtain this identifier.

     
  12. 12.

    Listing A-3 presents the DumpUserInfo application that was called for in Chapter 2.

     
import java.io.FileReader;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import static java.lang.System.*;
public class DumpUserInfo
{
   public static void main(String[] args)
   {
      try
      {
         SAXParserFactory spf =
            SAXParserFactory.newInstance();
         spf.setNamespaceAware(true);
         SAXParser sp = spf.newSAXParser();
         XMLReader xmlr = sp.getXMLReader();
         Handler handler = new Handler();
         xmlr.setContentHandler(handler);
         FileReader fr = new FileReader("tomcat-users.xml");
         xmlr.parse(new InputSource(fr));
      }
      catch (IOException ioe)
      {
         err.printf("IOE: %s%n", ioe.toString());
      }
      catch (ParserConfigurationException pce)
      {
         err.printf("PCE: %s%n", pce.toString());
      }
      catch (SAXException saxe)
      {
         err.printf("SAXE: %s%n", saxe.toString());
      }
   }
}
class Handler extends DefaultHandler
{
   @Override
   public void startElement(String uri, String localName,
                            String qName,
                            Attributes attributes)
   {
      if (localName.equals("user"))
      {
         for (int i = 0; i < attributes.getLength(); i++)
            out.printf("%s = %s%n",
                       attributes.getLocalName(i),
                       attributes.getValue(i));
         out.println();
      }
   }
}
Listing A-3

Using SAX to Dump the Apache tomcat-users.xml File’s User Information

  1. 13.

    Listings A-4 and A-5 present the SAXSearch and Handler classes that were called for in Chapter 2.

     
import java.io.FileReader;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import static java.lang.System.*;
public class SAXSearch
{
   final static String PROP_LH =
      "http://xml.org/sax/properties/lexical-handler";
   public static void main(String[] args)
   {
      if (args.length != 1)
      {
         err.println("usage: java SAXSearch publisher");
         return;
      }
      try
      {
         SAXParserFactory spf =
            SAXParserFactory.newInstance();
         spf.setNamespaceAware(true);
         SAXParser sp = spf.newSAXParser();
         XMLReader xmlr = sp.getXMLReader();
         Handler handler = new Handler(args[0]);
         xmlr.setContentHandler(handler);
         xmlr.setErrorHandler(handler);
         xmlr.setProperty(PROP_LH, handler);
         FileReader fr = new FileReader("books.xml");
         xmlr.parse(new InputSource(fr));
      }
      catch (IOException ioe)
      {
         err.printf("IOE: %s%n", ioe.toString());
      }
      catch (ParserConfigurationException pce)
      {
         err.printf("PCE: %s%n", pce.toString());
      }
      catch (SAXException saxe)
      {
         err.printf("SAXE: %s%n", saxe.toString());
      }
   }
}
Listing A-4

A SAX Driver Class for Searching books.xml for a Specific Publisher’s Books

import org.xml.sax.Attributes;
import org.xml.sax.SAXParseException;
import org.xml.sax.ext.DefaultHandler2;
import static java.lang.System.*;
public class Handler extends DefaultHandler2
{
   private boolean isPublisher, isTitle;
   private String isbn, publisher, pubYear, title, srchText;
   public Handler(String srchText)
   {
      this.srchText = srchText;
   }
   @Override
   public void characters(char[] ch, int start, int length)
   {
      if (isTitle)
      {
         title = new String(ch, start, length).trim();
         isTitle = false;
      }
      else
      if (isPublisher)
      {
         publisher = new String(ch, start, length).trim();
         isPublisher = false;
      }
   }
   @Override
   public void endElement(String uri, String localName,
                          String qName)
   {
      if (!localName.equals("book"))
         return;
      if (!srchText.equals(publisher))
         return;
      out.printf("title = %s, isbn = %s%n", title, isbn);
   }
   @Override
   public void error(SAXParseException saxpe)
   {
      out.printf("error() %s%n", saxpe.toString());
   }
   @Override
   public void fatalError(SAXParseException saxpe)
   {
      out.printf("fatalError() %s%n", saxpe.toString());
   }
   @Override
   public void startElement(String uri, String localName,
                            String qName, Attributes attributes)
   {
      if (localName.equals("title"))
      {
         isTitle = true;
         return;
      }
      else
      if (localName.equals("publisher"))
      {
         isPublisher = true;
         return;
      }
      if (!localName.equals("book"))
         return;
      for (int i = 0; i < attributes.getLength(); i++)
         if (attributes.getLocalName(i).equals("isbn"))
            isbn = attributes.getValue(i);
         else
         if (attributes.getLocalName(i).equals("pubyear"))
            pubYear = attributes.getValue(i);
   }
   @Override
   public void warning(SAXParseException saxpe)
   {
      out.printf("warning() %s%n", saxpe.toString());
   }
}
Listing A-5

A SAX Callback Class Whose Methods Are Called by the SAX Parser

  1. 14.

    When you use Listing 2-1’s SAXDemo application to validate Exercise A-22’s books.xml content against its DTD, you should observe no validation errors.

     

Chapter 3: Parsing and Creating XML Documents with DOM

  1. 1.

    DOM is a Java API for parsing an XML document into an in-memory tree of nodes and for creating an XML document from a tree of nodes. After a DOM parser has created a document tree, an application uses the DOM API to navigate over and extract infoset items from the tree’s nodes.

     
  2. 2.

    The answer is false: Java 11 supports DOM Levels 1, 2, and 3.

     
  3. 3.

    The 12 types of DOM nodes are attribute node, CDATA section node, comment node, document node, document fragment node, document type node, element node, entity node, entity reference node, notation node, processing-instruction node, and text node.

     
  4. 4.

    You obtain a document builder by first instantiating DocumentBuilderFactory via one of its newInstance() methods and then invoking newDocumentBuilder() on the returned DocumentBuilderFactory object to obtain a DocumentBuilder object.

     
  5. 5.

    You use a document builder to parse an XML document by invoking one of DocumentBuilder’s parse() methods.

     
  6. 6.

    The answer is true: Document and all other org.w3c.dom interfaces that describe different kinds of nodes are subinterfaces of the Node interface.

     
  7. 7.

    You use a document builder to create a new XML document by invoking DocumentBuilder’s Document newDocument() method and by invoking Document’s various “create” methods.

     
  8. 8.

    You would determine if a node has children by calling Node’s boolean hasChildNodes() method , which returns true when a node has child nodes.

     
  9. 9.

    The answer is false: when creating a new XML document, you cannot use the DOM API to specify the XML declaration’s encoding attribute.

     
  10. 10.

    The purpose of the Load and Save API is to provide a standard way to load XML content into a new DOM tree and save an existing DOM tree to an XML document.

     
  11. 11.

    The difference between NodeIterator and TreeWalker is as follows: A NodeIterator presents a flattened view of the subtree as an ordered sequence of nodes, presented in document order. Conversely, a TreeWalker maintains the hierarchical relationships of the subtree, allowing navigation of this hierarchy.

     
  12. 12.

    The difference between Range’s selectNode() and selectNodeContents() methods is as follows: selectNode() selects a node and its contents, whereas selectNodeContents() selects the contents within a node (without also selecting the node).

     
  13. 13.

    Listing A-6 presents the DumpUserInfo application that was called for in Chapter 3.

     
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import static java.lang.System.*;
public class DumpUserInfo
{
   public static void main(String[] args)
   {
      try
      {
         DocumentBuilderFactory dbf =
            DocumentBuilderFactory.newInstance();
         DocumentBuilder db = dbf.newDocumentBuilder();
         Document doc = db.parse("tomcat-users.xml");
         NodeList nl = doc.getChildNodes();
         for (int i = 0; i < nl.getLength(); i++)
         {
            Node node = nl.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE)
               dump((Element) node);
         }
      }
      catch (IOException ioe)
      {
         err.printf("IOE: %s%n", ioe.toString());
      }
      catch (SAXException saxe)
      {
         err.printf("SAXE: %s%n", saxe.toString());
      }
      catch (FactoryConfigurationError fce)
      {
         err.printf("FCE: %s%n", fce.toString());
      }
      catch (ParserConfigurationException pce)
      {
         err.printf("PCE: %s%n", pce.toString());
      }
   }
   static void dump(Element e)
   {
      if (e.getNodeName().equals("user"))
      {
         NamedNodeMap nnm = e.getAttributes();
         if (nnm != null)
            for (int i = 0; i < nnm.getLength(); i++)
            {
               Node node = nnm.item(i);
               Attr attr =
                  e.getAttributeNode(node.getNodeName());
               out.printf("%s = %s%n", attr.getName(),
                          attr.getValue());
            }
         out.println();
      }
      NodeList nl = e.getChildNodes();
      for (int i = 0; i < nl.getLength(); i++)
      {
         Node node = nl.item(i);
         if (node instanceof Element)
            dump((Element) node);
      }
   }
}
Listing A-6

Using DOM to Dump the Apache tomcat-users.xml File’s User Information

  1. 14.

    Listing A-7 presents the DOMSearch application that was called for in Chapter 3.

     
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import static java.lang.System.*;
public class DOMSearch
{
   public static void main(String[] args)
   {
      if (args.length != 1)
      {
         err.println("usage: java DOMSearch publisher");
         return;
      }
      try
      {
         DocumentBuilderFactory dbf =
            DocumentBuilderFactory.newInstance();
         DocumentBuilder db = dbf.newDocumentBuilder();
         Document doc = db.parse("books.xml");
         class BookItem
         {
            String title;
            String isbn;
         }
         List<BookItem> bookItems = new ArrayList<>();
         NodeList books = doc.getElementsByTagName("book");
         for (int i = 0; i < books.getLength(); i++)
         {
            Element book = (Element) books.item(i);
            NodeList children = book.getChildNodes();
            String title = "";
            for (int j = 0; j < children.getLength(); j++)
            {
               Node child = children.item(j);
               if (child.getNodeType() == Node.ELEMENT_NODE)
               {
                  if (child.getNodeName().equals("title"))
                     title = child.getFirstChild().
                                   getNodeValue().trim();
                  else
                  if (child.getNodeName().
                      equals("publisher"))
                  {
                     // Compare publisher name argument
                     // (args[0]) with text of publisher's
                     // child text node. The trim() method
                     // call removes whitespace that would
                     // interfere with the comparison.
                     if (args[0].
                         equals(child.getFirstChild().
                                     getNodeValue().trim()))
                     {
                        BookItem bookItem = new BookItem();
                        bookItem.title = title;
                        NamedNodeMap nnm =
                           book.getAttributes();
                        Node isbn =
                           nnm.getNamedItem("isbn");
                        bookItem.isbn = isbn.getNodeValue();
                        bookItems.add(bookItem);
                        break;
                     }
                  }
               }
            }
         }
         for (BookItem bookItem: bookItems)
            out.printf("title = %s, isbn = %s%n",
                       bookItem.title, bookItem.isbn);
      }
      catch (IOException ioe)
      {
         err.printf("IOE: %s%n", ioe.toString());
      }
      catch (SAXException saxe)
      {
         err.printf("SAXE: %s%n", saxe.toString());
      }
      catch (FactoryConfigurationError fce)
      {
         err.printf("FCE: %s%n", fce.toString());
      }
      catch (ParserConfigurationException pce)
      {
         err.printf("PCE: %s%n", pce.toString());
      }
   }
}
Listing A-7

Using DOM to Search books.xmlfor a Specific Publisher’s Books

  1. 15.

    Listing A-8 presents the DOMValidate application that was called for in Chapter 3.

     
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import static java.lang.System.*;
public class DOMValidate
{
   public static void main(String[] args)
   {
      if (args.length != 1)
      {
         err.println("usage: java DOMValidate xmlfile");
         return;
      }
      try
      {
         DocumentBuilderFactory dbf =
            DocumentBuilderFactory.newInstance();
         dbf.setNamespaceAware(true);
         dbf.setValidating(true);
         DocumentBuilder db = dbf.newDocumentBuilder();
         Document doc = db.parse(args[0]);
         out.printf("Version = %s%n", doc.getXmlVersion());
         out.printf("Encoding = %s%n",
                    doc.getXmlEncoding());
         out.printf("Standalone = %b%n%n",
                    doc.getXmlStandalone());
         if (doc.hasChildNodes())
         {
            NodeList nl = doc.getChildNodes();
            for (int i = 0; i < nl.getLength(); i++)
            {
               Node node = nl.item(i);
               if (node.getNodeType() == Node.ELEMENT_NODE)
                  dump((Element) node);
            }
         }
      }
      catch (IOException ioe)
      {
         err.printf("IOE: %s%n", ioe.toString());
      }
      catch (SAXException saxe)
      {
         err.printf("SAXE: %s%n", saxe.toString());
      }
      catch (FactoryConfigurationError fce)
      {
         err.printf("FCE: %s%n", fce.toString());
      }
      catch (ParserConfigurationException pce)
      {
         err.printf("PCE: %s%n", pce.toString());
      }
   }
   static void dump(Element e)
   {
      out.printf("Element: %s, %s, %s, %s%n",
                 e.getNodeName(), e.getLocalName(),
                 e.getPrefix(), e.getNamespaceURI());
      NamedNodeMap nnm = e.getAttributes();
      if (nnm != null)
         for (int i = 0; i < nnm.getLength(); i++)
         {
            Node node = nnm.item(i);
            Attr attr =
               e.getAttributeNode(node.getNodeName());
            out.printf("Attribute %s = %s%n",
                       attr.getName(), attr.getValue());
         }
      NodeList nl = e.getChildNodes();
      for (int i = 0; i < nl.getLength(); i++)
      {
         Node node = nl.item(i);
         if (node instanceof Element)
            dump((Element) node);
      }
   }
}
Listing A-8

Using DOM to Validate XML Content

  1. 16.

    Listing A-9 presents the DOMDemo application that was called for in Chapter 3.

     
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.DOMError;
import org.w3c.dom.DOMErrorHandler;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSParser;
import static java.lang.System.*;
class ErrHandler implements DOMErrorHandler
{
   @Override
   public boolean handleError(DOMError error)
   {
      short severity = error.getSeverity();
      if (severity == error.SEVERITY_ERROR)
         System.out.printf("DOM3 error: %s%n",
                           error.getMessage());
      else
      if (severity == error.SEVERITY_FATAL_ERROR)
         System.out.printf("DOM3 fatal error: %s%n",
                           error.getMessage());
      else
      if (severity == error.SEVERITY_WARNING)
         System.out.printf("DOM3 warning: %s%n",
                           error.getMessage());
      return true;
   }
}
public class DOMDemo
{
   public static void main(String[] args) throws Exception
   {
      if (args.length != 1)
      {
         err.println("usage: java DOMDemo xmlfile");
         return;
      }
      DOMImplementationLS ls = (DOMImplementationLS)
         DOMImplementationRegistry.newInstance().
         getDOMImplementation("LS");
      LSParser parser =
         ls.createLSParser(DOMImplementationLS.
                           MODE_SYNCHRONOUS, null);
      DOMConfiguration config = parser.getDomConfig();
      config.setParameter("validate", Boolean.TRUE);
      config.setParameter("error-handler",
                          new ErrHandler());
      Document doc = parser.parseURI(args[0]);
      if (doc.hasChildNodes())
      {
         NodeList nl = doc.getChildNodes();
         for (int i = 0; i < nl.getLength(); i++)
         {
            Node node = nl.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE)
               dump((Element) node);
         }
      }
   }
   static void dump(Element e)
   {
      System.out.printf("Element: %s, %s, %s, %s%n",
                        e.getNodeName(), e.getLocalName(),
                        e.getPrefix(), e.getNamespaceURI());
      NamedNodeMap nnm = e.getAttributes();
      if (nnm != null)
         for (int i = 0; i < nnm.getLength(); i++)
         {
            Node node = nnm.item(i);
            Attr attr =
               e.getAttributeNode(node.getNodeName());
            out.printf("  Attribute %s = %s%n",
                       attr.getName(), attr.getValue());
         }
      NodeList nl = e.getChildNodes();
      for (int i = 0; i < nl.getLength(); i++)
      {
         Node node = nl.item(i);
         if (node instanceof Element)
            dump((Element) node);
      }
   }
}
Listing A-9

Installing a Custom Error Handler

Chapter 4: Parsing and Creating XML Documents with StAX

  1. 1.

    StAX is a Java API for parsing an XML document sequentially from start to finish and also for creating XML documents.

     
  2. 2.

    The javax.xml.stream, javax.xml.stream.events, and javax.xml.stream.util packages make up the StAX API.

     
  3. 3.

    The answer is false: an event-based reader extracts the next infoset item from an input stream by obtaining an event.

     
  4. 4.

    You obtain a document reader by calling one of the various “create” methods that are declared in the XMLInputFactory class. You obtain a document writer by calling one of the various “create” methods that are declared in the XMLOutputFactory class.

     
  5. 5.

    When you call XMLOutputFactory’s void setProperty(String name, Object value) method with XMLOutputFactory.IS_REPAIRING_NAMESPACES as the property name and true as the value, the document writer takes care of all namespace bindings and declarations, with minimal help from the application. The output is always well formed with respect to namespaces.

     
  6. 6.

    Listing A-10 presents the ParseXMLDoc application that was called for in Chapter 4.

     
import java.io.FileReader;
import java.io.IOException;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import static java.lang.System.*;
public class ParseXMLDoc
{
   public static void main(String[] args)
   {
      if (args.length != 1)
      {
         err.println("usage: java ParseXMLDoc pathname");
         return;
      }
      XMLInputFactory xmlif = XMLInputFactory.newFactory();
      XMLStreamReader xmlsr = null;
      try (var fr = new FileReader(args[0]))
      {
         xmlsr = xmlif.createXMLStreamReader(fr);
         int item = xmlsr.getEventType();
         if (item != XMLStreamReader.START_DOCUMENT)
         {
            err.println("START_DOCUMENT expected");
            return;
         }
         while ((item = xmlsr.next()) !=
                XMLStreamReader.END_DOCUMENT)
            switch (item)
            {
               case XMLStreamReader.ATTRIBUTE:
                  out.println("ATTRIBUTE");
                  break;
               case XMLStreamReader.CDATA:
                  out.println("CDATA");
                  break;
               case XMLStreamReader.CHARACTERS:
                  out.println("CHARACTERS");
                  break;
               case XMLStreamReader.COMMENT:
                  out.println("COMMENT");
                  break;
               case XMLStreamReader.DTD:
                  out.println("DTD");
                  break;
               case XMLStreamReader.END_ELEMENT:
                  out.println("END_ELEMENT");
                  break;
               case XMLStreamReader.ENTITY_DECLARATION:
                  out.println("ENTITY_DECLARATION");
                  break;
               case XMLStreamReader.ENTITY_REFERENCE:
                  out.println("ENTITY_REFERENCE");
                  break;
               case XMLStreamReader.NAMESPACE:
                  out.println("NAMESPACE");
                  break;
               case XMLStreamReader.NOTATION_DECLARATION:
                  out.println("NOTATION_DECLARATION");
                  break;
               case XMLStreamReader.PROCESSING_INSTRUCTION:
                  out.println("PROCESSING_INSTRUCTION");
                  break;
               case XMLStreamReader.SPACE:
                  out.println("SPACE");
                  break;
               case XMLStreamReader.START_ELEMENT:
                  out.println("START_ELEMENT");
                  out.printf("Name = %s%n",
                             xmlsr.getName());
                  out.printf("Local name = %s%n",
                             xmlsr.getLocalName());
                  int nAttrs = xmlsr.getAttributeCount();
                  for (int i = 0; i < nAttrs; i++)
                     out.printf("Attribute [%s,%s]%n",
                                xmlsr.
                                   getAttributeLocalName(i),
                                xmlsr.getAttributeValue(i));
            }
      }
      catch (IOException ioe)
      {
         ioe.printStackTrace();
      }
      catch (XMLStreamException xmlse)
      {
         xmlse.printStackTrace();
      }
      finally
      {
         if (xmlsr != null)
            try
            {
               xmlsr.close();
            }
            catch (XMLStreamException xmlse)
            {
               err.printf("XMLSE: %s%n",
                          xmlse.getMessage());
            }
      }
   }
}
Listing A-10

A StAX Stream-Based Parser for Parsing an XML Document

When you run this application against Exercise A-21’s books.xml file (without an internal DTD) via java ParseXMLDoc books.xml , you should observe the following output:
START_ELEMENT
Name = books
Local name = books
CHARACTERS
START_ELEMENT
Name = book
Local name = book
Attribute [isbn,0201548550]
Attribute [pubyear,1992]
CHARACTERS
START_ELEMENT
Name = title
Local name = title
CHARACTERS
END_ELEMENT
CHARACTERS
START_ELEMENT
Name = author
Local name = author
CHARACTERS
END_ELEMENT
CHARACTERS
START_ELEMENT
Name = publisher
Local name = publisher
CHARACTERS
END_ELEMENT
CHARACTERS
END_ELEMENT
CHARACTERS
START_ELEMENT
Name = book
Local name = book
Attribute [isbn,9781430210450]
Attribute [pubyear,2008]
CHARACTERS
START_ELEMENT
Name = title
Local name = title
CHARACTERS
END_ELEMENT
CHARACTERS
START_ELEMENT
Name = author
Local name = author
CHARACTERS
END_ELEMENT
CHARACTERS
START_ELEMENT
Name = author
Local name = author
CHARACTERS
END_ELEMENT
CHARACTERS
START_ELEMENT
Name = author
Local name = author
CHARACTERS
END_ELEMENT
CHARACTERS
START_ELEMENT
Name = publisher
Local name = publisher
CHARACTERS
END_ELEMENT
CHARACTERS
END_ELEMENT
CHARACTERS
START_ELEMENT
Name = book
Local name = book
Attribute [isbn,0201310058]
Attribute [pubyear,2001]
CHARACTERS
START_ELEMENT
Name = title
Local name = title
CHARACTERS
END_ELEMENT
CHARACTERS
START_ELEMENT
Name = author
Local name = author
CHARACTERS
END_ELEMENT
CHARACTERS
START_ELEMENT
Name = publisher
Local name = publisher
CHARACTERS
END_ELEMENT
CHARACTERS
END_ELEMENT
CHARACTERS
END_ELEMENT

Chapter 5: Selecting Nodes with XPath

  1. 1.

    XPath is a nonXML declarative query language (defined by the W3C) for selecting an XML document’s infoset items as one or more nodes.

     
  2. 2.

    XPath is commonly used to simplify access to a DOM tree’s nodes and in the context of XSLT to select those input document elements (via XPath expressions) that are to be copied to an output document.

     
  3. 3.

    The seven kinds of nodes that XPath recognizes are element, attribute, text, namespace, processing instruction, comment, and document.

     
  4. 4.

    The answer is false: XPath doesn’t recognize CDATA sections.

     
  5. 5.

    XPath provides location path expressions for selecting nodes. A location path expression locates nodes via a sequence of steps starting from the context node, which is the root node or some other document node that is the current node. The returned set of nodes might be empty, or it might contain one or more nodes.

     
  6. 6.

    The answer is true: in a location path expression, you must prefix an attribute name with the @ symbol.

     
  7. 7.

    The functions that XPath provides for selecting comment, text, and processing-instruction nodes are comment(), text(), and processing-instruction().

     
  8. 8.

    XPath provides wildcards for selecting unknown nodes. The * wildcard matches any element node regardless of the node’s type. It doesn’t match attributes, text nodes, comments, or processing-instruction nodes. When you place a namespace prefix before the *, only elements belonging to that namespace are matched. The node() wildcard is a function that matches all nodes. Finally, the @* wildcard matches all attribute nodes.

     
  9. 9.

    You perform multiple selections by using the vertical bar (|). For example, author/*|publisher/* selects the children of author and the children of publisher.

     
  10. 10.

    A predicate is a square bracket-delimited Boolean expression that’s tested against each selected node. If the expression evaluates to true, that node is included in the set of nodes returned by the XPath expression; otherwise, the node isn’t included in the set.

     
  11. 11.

    The functions that XPath provides for working with nodesets are last(), position(), id(), local-name(), namespace-uri(), and name().

     
  12. 12.

    The three advanced features that the XPath API provides to overcome limitations with the XPath 1.0 language are namespace contexts, extension functions and function resolvers, and variables and variable resolvers.

     
  13. 13.

    The answer is false: the XPath API maps XPath’s number type to java.lang.Double.

     
  14. 14.

    Listings A-11 and A-12 present the contacts.xml document file and XPathSearch application that were called for in Chapter 5.

     
<?xml version="1.0"?>
<contacts>
   <contact>
      <Name>John Doe</Name>
      <city>Chicago</city>
      <city>Denver</city>
   </contact>
   <contact>
      <name>Jane Doe</name>
      <city>New York</city>
   </contact>
   <contact>
      <name>Sandra Smith</name>
      <city>Denver</city>
      <city>Miami</city>
   </contact>
   <contact>
      <name>Bob Jones</name>
      <city>Chicago</city>
   </contact>
</contacts>
Listing A-11

A Contacts Document with a Titlecased Name Element

import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathException;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import static java.lang.System.*;
public class XPathSearch
{
   final static String EXPR =
      "//contact[city = 'Chicago']/name/text()|" +
      "//contact[city = 'Chicago']/Name/text()";
   public static void main(String[] args)
   {
      try
      {
         DocumentBuilderFactory dbf =
            DocumentBuilderFactory.newInstance();
         DocumentBuilder db = dbf.newDocumentBuilder();
         Document doc = db.parse("contacts.xml");
         XPathFactory xpf = XPathFactory.newInstance();
         XPath xp = xpf.newXPath();
         XPathExpression xpe;
         xpe = xp.compile(EXPR);
         Object result =
            xpe.evaluate(doc, XPathConstants.NODESET);
         NodeList nl = (NodeList) result;
         for (int i = 0; i < nl.getLength(); i++)
            out.println(nl.item(i).getNodeValue());
      }
      catch (IOException ioe)
      {
         err.printf("IOE: %s%n", ioe.toString());
      }
      catch (SAXException saxe)
      {
         err.printf("SAXE: %s%n", saxe.toString());
      }
      catch (FactoryConfigurationError fce)
      {
         err.printf("FCE: %s%n", fce.toString());
      }
      catch (ParserConfigurationException pce)
      {
         err.printf("PCE: %s%n", pce.toString());
      }
      catch (XPathException xpe)
      {
         err.printf("XPE: %s%n", xpe.toString());
      }
   }
}
Listing A-12

Searching for Name or Name Elements via a Multiple Selection

Chapter 6: Transforming XML Documents with XSLT

  1. 1.

    XSLT is a family of languages for transforming and formatting XML documents.

     
  2. 2.

    XSLT accomplishes its work by using XSLT processors and stylesheets. An XSLT processor is a software component that applies an XSLT stylesheet to an input document (without modifying the document), and copies the transformed result to a result tree, which can be output to a file or output stream, or even piped into another XSLT processor for additional transformations.

     
  3. 3.

    The answer is false: call Transformer’s void transform(Source xmlSource, Result outputTarget) method to transform a source to a result.

     
  4. 4.

    Listings A-13 and A-14 present the books.xsl document stylesheet file and MakeHTML application that were called for in Chapter 6.

     
<?xml version="1.0"?>
<xsl:stylesheet
   version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/books">
<html>
<head>
<title>Books</title>
</head>
<body>
<xsl:for-each select="book">
<h2>
<xsl:value-of select="normalize-space(title/text())"/>
</h2>
ISBN: <xsl:value-of select="@isbn"/><br/>
Publication Year: <xsl:value-of select="@pubyear"/><br/>
<br/><xsl:text>
</xsl:text>
<xsl:for-each select="author">
<xsl:value-of select="normalize-space(text())"/>
<br/><xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Listing A-13

A Stylesheet for Converting books.xml Content to HTML

import java.io.FileReader;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import static java.lang.System.*;
public class MakeHTML
{
   public static void main(String[] args)
   {
      try
      {
         DocumentBuilderFactory dbf =
            DocumentBuilderFactory.newInstance();
         DocumentBuilder db = dbf.newDocumentBuilder();
         Document doc = db.parse("books.xml");
         TransformerFactory tf =
            TransformerFactory.newInstance();
         StreamSource ssStyleSheet;
         FileReader fr = new FileReader("books.xsl");
         ssStyleSheet = new StreamSource(fr);
         Transformer t = tf.newTransformer(ssStyleSheet);
         t.setOutputProperty(OutputKeys.METHOD, "html");
         t.setOutputProperty(OutputKeys.INDENT, "yes");
         Source source = new DOMSource(doc);
         Result result = new StreamResult(out);
         t.transform(source, result);
      }
      catch (IOException ioe)
      {
         err.printf("IOE: %s%n", ioe.toString());
      }
      catch (FactoryConfigurationError fce)
      {
         err.printf("FCE: %s%n", fce.toString());
      }
      catch (ParserConfigurationException pce)
      {
         err.printf("PCE: %s%n", pce.toString());
      }
      catch (SAXException saxe)
      {
         err.printf("SAXE: %s%n", saxe.toString());
      }
      catch (TransformerConfigurationException tce)
      {
         err.printf("TCE: %s%n", tce.toString());
      }
      catch (TransformerException te)
      {
         err.printf("TE: %s%n", te.toString());
      }
      catch (TransformerFactoryConfigurationError tfce)
      {
         err.printf("TFCE: %s%n", tfce.toString());
      }
   }
}
Listing A-14

Converting Books XML to HTML via a Stylesheet

Chapter 7: Introducing JSON

  1. 1.

    JSON (JavaScript Object Notation) is a language-independent data format that expresses JSON objects as human-readable lists of properties.

     
  2. 2.

    The answer is false: JSON is derived from a nonstrict subset of JavaScript.

     
  3. 3.

    The JSON data format presents a JSON object as a brace-delimited and comma-separated list of properties.

     
  4. 4.

    The six types that JSON supports are number, string, Boolean, array, object, and null.

     
  5. 5.

    The answer is true: JSON doesn’t support comments.

     
  6. 6.

    You would parse a JSON object into an equivalent JavaScript object by calling the JSON object’s parse() method with the text to be parsed as this method’s argument.

     
  7. 7.

    JSON Schema is a grammar language for defining the structure, content, and (to some extent) semantics of JSON objects.

     
  8. 8.

    When creating a schema, you identify those properties that must be present in those JSON objects that the schema validates by placing their names in the array that’s assigned to the schema’s required property name.

     
  9. 9.

    Listing A-15 presents the JSON object that was called for in Chapter 7.

     
{
   "name": "hammer",
   "price": 20
}
Listing A-15

A Product in Terms of Name and Price

  1. 10.

    Listing A-16 presents the schema that was called for in Chapter 7.

     
{
   "$schema": "http://json-schema.org/draft-07/schema#",
   "title": "Product",
   "description": "A product",
   "type": "object",
   "properties":
   {
      "name":
      {
         "description": "A product name",
         "type": "string"
      },
      "price":
      {
         "description": "A product price",
         "type": "number",
         "minimum": 1
      }
   },
   "required": ["name", "price"]
}
Listing A-16

A Schema for Validating Product Objects

Chapter 8: Parsing and Creating JSON Objects with mJson

  1. 1.

    mJson is a small Java-based JSON library for parsing JSON objects into Java objects and vice versa.

     
  2. 2.

    The Json class describes a JSON object or part of a JSON object. It contains Schema and Factory interfaces, more than 50 methods, and other members.

     
  3. 3.

    Json’s methods for reading and parsing external JSON objects are Json read(String s), Json read(URL url), and Json read(CharacterIterator ci).

     
  4. 4.

    The answer is true: the read() methods can also parse smaller JSON fragments, such as an array of different-typed values.

     
  5. 5.

    The methods that Json provides for creating JSON objects are Json array(), Json array(Object... args), Json make(Object anything), Json nil(), Json object(), and Json object(Object... args).

     
  6. 6.

    Json’s boolean isPrimitive() method returns true when the invoking Json object describes a JSON number, string, or Boolean value.

     
  7. 7.

    You return a Json object’s JSON array by calling List<Json> asJsonList() to return a list of Json objects (one per array element) or by calling List<Object> asList() to return a list of Java objects (each object describes one of the elements).

     
  8. 8.

    The answer is false: Json’s Map<String, Object> asMap() method returns a map of the properties of a Json object that describes a JSON object. The returned map is a copy, and modifications to it don’t affect the Json object.

     
  9. 9.

    Json’s Json at(int index), Json at(String propName), Json at(String propName, Json defValue), and Json at(String propName, Object defValue) methods let you access the contents of arrays and objects.

     
  10. 10.

    Json’s boolean is(int index, Object value) method returns true when this Json object describes a JSON array that has the specified value at the specified index; otherwise, it returns false.

     
  11. 11.

    When you attempt to set the value for a nonexistent array element, Json throws IndexOutOfBoundsException.

     
  12. 12.

    The difference between Json’s atDel() and delAt() methods is as follows: the atDel() methods return the removed array element or object property, whereas the delAt() methods do not return the removed array element or object property.

     
  13. 13.

    Json’s Json with(Json objectorarray) method combines this Json object’s JSON object or JSON array with the argument passed to objectorarray. The JSON type of this Json object and the JSON type of objectorarray must match. If objectorarray identifies a JSON object, all of its properties are appended to this Json object’s object. If objectorarray identifies a JSON array, all of its elements are appended to this Json object’s array.

     
  14. 14.

    Json’s methods for obtaining a Json.Schema object are Json.Schema schema(Json jsonSchema), Json.Schema schema(Json jsonSchema, URI uri), and Json.Schema schema(URI uri).

     
  15. 15.

    You validate a JSON document against a schema by calling Json.Schema’s Json validate(Json document) method with the JSON document passed as a Json argument to this method.

     
  16. 16.

    The difference between Json’s setGlobalFactory() and attachFactory() methods is that setGlobalFactory() installs the specified factory as a global factory, which is used by all threads that don’t have a specific thread-local factory attached to them, whereas attachFactory() attaches the specified factory to the invoking thread only.

     
  17. 17.

    The Json dup() method returns a clone (a duplicate) of this Json entity. The String pad(String callback) method wraps a function named callback around the JSON object described by the current Json object. This is done for the reason explained in Wikipedia’s “JSONP” entry ( https://en.wikipedia.org/wiki/JSONP ).

     
  18. 18.

    Listing A-17 presents the mJsonDemo application that was called for in Chapter 8.

     
import mjson.Json;
import static java.lang.System.*;
public class mJsonDemo
{
   public static void main(String[] args)
   {
      Json json1 = Json.read("{"name": "John Doe"}");
      Json json2 = json1.dup();
      out.println(json1);
      out.println();
      out.println(json2);
      out.println();
      out.printf("json1 == json2: %b%n", json1 == json2);
      out.printf("json1.equals(json2): %b%n",
                 json1.equals(json2));
      out.println();
      out.println(json1.pad("func"));
      /*
         The following output is generated:
         {"name":"John Doe"}
         {"name":"John Doe"}
         json1 == json2: false
         json1.equals(json2): true
         func({"name":"John Doe"});
      */
   }
}
Listing A-17

Demonstrating Json’s dup() and pad() Methods

Chapter 9: Parsing and Creating JSON Objects with Gson

  1. 1.

    Gson is a small Java-based library for parsing and creating JSON objects. Google developed Gson for its own projects, but later made Gson publicly available, starting with version 1.0.

     
  2. 2.

    Gson’s packages are com.google.gson (provides access to Gson, the main class for working with Gson), com.google.gson.annotations (provides annotation types for use with Gson), com.google.gson.reflect (provides a utility class for obtaining type information from a generic type), and com.google.gson.stream (provides utility classes for reading and writing JSON-encoded values).

     
  3. 3.

    The two ways to obtain a Gson object are to call the Gson() constructor or to invoke the create() method on a GsonBuilder object.

     
  4. 4.

    The types for which Gson provides default serialization and deserialization are java.lang.Enum, java.util. Map , java.net . URL , java.net . URI , java.util. Locale , java.util. Date , java.math. BigDecimal , and java.math. BigInteger .

     
  5. 5.

    You would enable pretty-printing by calling GsonBuilder’s setPrettyPrinting() method .

     
  6. 6.

    The answer is true: by default, Gson excludes transient or static fields from consideration for serialization and deserialization.

     
  7. 7.

    Once you have a Gson object, you can call various fromJson() and toJson() methods to convert between JSON and Java objects.

     
  8. 8.

    You use Gson to customize JSON object parsing by implementing the JsonDeserializer<T> interface , instantiating an object from the implementation, and registering with Gson the deserializer object along with the class object of the Java class whose objects are to be serialized/deserialized.

     
  9. 9.

    The JsonElement class represents a JSON element (such as a number, a Boolean value, or an array). It provides various methods for obtaining an element value, such as double getAsDouble(), boolean getAsBoolean(), and JsonArray getAsJsonArray().

     
  10. 10.

    The JsonElement subclasses are JsonArray, JsonNull, JsonObject, and JsonPrimitive.

     
  11. 11.

    You call GsonBuilder’s GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) method to register a serializer or deserializer with a Gson object.

     
  12. 12.

    JsonSerializer provides the JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) method to serialize a Java object to a JSON object.

     
  13. 13.

    Gson provides the Expose, JsonAdapter, SerializedName, Since, and Until annotation types to simplify serialization and deserialization.

     
  14. 14.

    The answer is false: to use Expose, it’s not enough to annotate a field, as in @Expose(serialize = true, deserialize = false). You also have to call GsonBuilder’s GsonBuilder excludeFieldsWithoutExposeAnnotation() method.

     
  15. 15.

    JsonSerializationContext and JsonDeserializationContext provide access to methods for performing default serialization and default deserialization, which are handy when dealing with nested arrays and objects that don’t require special treatment.

     
  16. 16.

    The answer is false: you can call <T> T fromJson( String json, Class <T> classOfT) to deserialize nongeneric objects (i.e., objects created from nongeneric classes) only.

     
  17. 17.

    You should prefer TypeAdapter to JsonSerializer and JsonDeserializer because TypeAdapter is more efficient. Unlike JsonSerializer and JsonDeserializer , which are associated with an intermediate layer of code that converts Java and JSON objects to JsonElements, TypeAdapter doesn’t perform this conversion.

     
  18. 18.

    Listing A-18 presents the GsonDemo application that was called for in Chapter 9.

     
import java.lang.reflect.Modifier;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.Expose;
import static java.lang.System.*;
public class GsonDemo
{
   static class SomeClass
   {
      transient int id;
      @Expose(serialize = true, deserialize = true)
      transient String password;
      @Expose(serialize = false, deserialize = false)
      int field1;
      @Expose(serialize = false, deserialize = true)
      int field2;
      @Expose(serialize = true, deserialize = false)
      int field3;
      @Expose(serialize = true, deserialize = true)
      int field4;
      @Expose(serialize = true, deserialize = true)
      static int field5;
      static int field6;
   }
   public static void main(String[] args)
   {
      SomeClass sc = new SomeClass();
      sc.id = 1;
      sc.password = "abc";
      sc.field1 = 2;
      sc.field2 = 3;
      sc.field3 = 4;
      sc.field4 = 5;
      sc.field5 = 6;
      sc.field6 = 7;
      GsonBuilder gsonb = new GsonBuilder();
      gsonb.excludeFieldsWithoutExposeAnnotation();
      gsonb.excludeFieldsWithModifiers(Modifier.TRANSIENT);
      Gson gson = gsonb.create();
      String json = gson.toJson(sc);
      out.println(json);
      SomeClass sc2 = gson.fromJson(json, SomeClass.class);
      out.printf("id = %d%n", sc2.id);
      out.printf("password = %s%n", sc2.password);
      out.printf("field1 = %d%n", sc2.field1);
      out.printf("field2 = %d%n", sc2.field2);
      out.printf("field3 = %d%n", sc2.field3);
      out.printf("field4 = %d%n", sc2.field4);
      out.printf("field5 = %d%n", sc2.field5);
      out.printf("field6 = %d%n", sc2.field6);
   }
}
Listing A-18

Serializing and Deserializing Properly Exposed Static Fields

The gsonb.excludeFieldsWithModifiers(Modifier.TRANSIENT); expression prevents only transient fields from being serialized and deserialized: static fields will be serialized and deserialized, by default. Of course, static fields that are not annotated with @Expose have no chance to be serialized and deserialized, because of gsonb.excludeFieldsWithoutExposeAnnotation();.

When you run this application, you should discover the following output:
{"field3":4,"field4":5,"field5":6}
id = 0
password = null
field1 = 0
field2 = 0
field3 = 0
field4 = 5
field5 = 6
field6 = 7

The first line shows that the static field named field5 was serialized.

Chapter 10: Extracting JSON Values with JsonPath

  1. 1.

    JsonPath is a declarative query language (also known as a path-expression-syntax) for selecting and extracting a JSON document’s property values.

     
  2. 2.

    The answer is false: JsonPath is based on XPath 1.0.

     
  3. 3.

    The operator that represents the root JSON object is $.

     
  4. 4.

    You can specify JsonPath expressions in dot notation and square bracket notation.

     
  5. 5.

    The @ operator represents the current node being processed by a filter predicate.

     
  6. 6.

    The answer is false: JsonPath’s deep scan operator (..) is equivalent to XPath’s // symbol.

     
  7. 7.

    JsonPath’s JsonPath compile(String jsonPath, Predicate... filters) static method compiles the JsonPath expression stored in the jsonPath-referenced string to a JsonPath object (to improve performance when JsonPath expressions are reused). The array of predicates is applied to ? placeholders appearing in the string.

     
  8. 8.

    The return type of the <T> T read(String json) generic method that returns JSON object property names and their values is LinkedHashMap.

     
  9. 9.

    The three predicate categories are inline predicates, filter predicates, and custom predicates.

     
  10. 10.

    Listing A-19 presents the JsonPathDemo application that was called for in Chapter 10.

     
import com.jayway.jsonpath.JsonPath;
import static java.lang.System.*;
public class JsonPathDemo
{
   public static void main(String[] args)
   {
      String json =
      "{" +
      "   "numbers": [10, 20, 25, 30]" +
      "}";
      String expr = "$.numbers.max()";
      double d = JsonPath.read(json, expr);
      out.printf("Max value = %f%n", d);
      expr = "$.numbers.min()";
      d = JsonPath.read(json, expr);
      out.printf("Min value = %f%n", d);
      expr = "$.numbers.avg()";
      d = JsonPath.read(json, expr);
      out.printf("Average value = %f%n", d);
   }
}
Listing A-19

Extracting and Outputting Maximum, Minimum, and Average Numeric Values

Chapter 11: Processing JSON with Jackson

  1. 1.

    Jackson is a suite of data-processing tools for Java. These tools include a streaming JSON parser/generator library, a matching data-binding library (for converting Plain Old Java Objects [POJOs] to and from JSON), and additional data format modules for processing data encoded in XML and other formats.

     
  2. 2.

    Jackson’s packages include Jackson Core (com.fasterxml.jackson.core), Jackson Databind (com.fasterxml.jackson.databind), and Jackson Annotations (com.fasterxml.jackson.annotation).

     
  3. 3.

    The answer is false: Jackson supports simple data binding and full (also known as POJO) data binding.

     
  4. 4.

    Streaming in Jackson deserializes (reads) and serializes (writes) JSON content as discrete events. Reading is performed by a parser that tokenizes JSON content into tokens and associated data; writing is performed by a generator that constructs JSON content based on a sequence of calls that output JSON tokens.

     
  5. 5.

    The answer is false: streaming is the most efficient way to process JSON content.

     
  6. 6.

    You create a stream-based parser by instantiating the JsonFactory class and invoking one of this class’s overloaded createParser() methods on the instance to obtain a JsonParser instance.

     
  7. 7.

    After you obtain a parser, you enter a loop that repeats until the parser’s isClosed() method returns true. Each loop iteration invokes JsonParser’s nextToken() method, which returns a JsonToken object that identifies the next token from the JSON content. You can interrogate this object to obtain additional information about the token and then take appropriate action.

     
  8. 8.

    You create a stream-based generator by instantiating the JsonFactory class and invoking one of this class’s overloaded createGenerator() methods on the instance to obtain a JsonGenerator instance.

     
  9. 9.

    After you obtain a generator, you invoke JsonGenerator methods such as writeStartObject() and writeStringField() to output JSON content. You complete this task by invoking JsonGenerator’s close() method.

     
  10. 10.

    The answer is true: the tree model provides a mutable in-memory tree representation of a JSON document.

     
  11. 11.

    The ObjectMapper class is used to start building a tree. The tree’s nodes are instances of classes that descend from the abstract JsonNode class.

     
  12. 12.

    You read a JSON document into an in-memory tree by invoking one of ObjectMapper’s readTree() methods .

     
  13. 13.

    The difference between JsonNode get(int index) and JsonNode path(int index) is that get() returns null for a missing value, whereas path() returns a MissingNode reference for a missing value.

     
  14. 14.

    You write a tree to a JSON document by invoking one of ObjectMapper’s writeTree() methods .

     
  15. 15.

    Data binding in Jackson is parsing JSON content to and from Java objects such as POJOs. JSON content is deserialized into Java objects, and Java objects are serialized into JSON content.

     
  16. 16.

    The purpose of the TypeReference class is to pass a generic type definition (removed by type erasure) to one of ObjectMapper’s readValue() methods.

     
  17. 17.

    Simple data binding differs from full data binding in that simple data binding converts to and from a limited number of core JDK types, whereas full data binding also converts to and from any Java bean type.

     
  18. 18.

    By default, Jackson maps the fields of a JSON object to fields in a Java object by matching the names of the JSON fields to the getter and setter methods in the Java object. Jackson removes the get and set parts of the names of the getter and setter methods and converts the first character of the remaining name to lowercase.

     
  19. 19.

    The answer is false: a getter method makes a non-public field serializable and deserializable.

     
  20. 20.

    Jackson’s read-only annotation types are JsonSetter, JsonAnySetter, JsonCreator and JsonProperty, JacksonInject, and JsonDeserialize.

     
  21. 21.

    The JsonPropertyOrder annotation type specifies the order in which a Java object’s fields should be serialized to JSON content.

     
  22. 22.

    The difference between a stateful and a stateless pretty printer class is that the stateful class must implement the Instantiatable<T> interface, to allow for the construction of per-generation instances in order to avoid state corruption when sharing the pretty printer instance among threads. This is not a requirement for a stateless class.

     
  23. 23.

    You prevent ObjectMapper’s writeValue() methods from closing the System.out stream by executing disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET) on the ObjectMapper instance.

     
  24. 24.

    Listing A-20 presents the JacksonDemo application that was called for in Chapter 11.

     
import java.io.File;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import static java.lang.System.*;
public class JacksonDemo
{
   public static void main(String[] args) throws Exception
   {
      JsonFactory factory = new JsonFactory();
      JsonGenerator generator =
      factory.createGenerator(new File("person.json"),
                              JsonEncoding.UTF8);
      generator.enable(JsonGenerator.Feature.
                       WRITE_NUMBERS_AS_STRINGS);
      generator.writeStartObject();
      generator.writeStringField("firstname", "John");
      generator.writeStringField("lastName", "Doe");
      generator.writeNumberField("age", 42);
      generator.writeFieldName("address");
      generator.writeStartObject();
      generator.writeStringField("street", "400 Some Street");
      generator.writeStringField("city", "Beverly Hills");
      generator.writeStringField("state", "CA");
      generator.writeNumberField("zipcode", 90210);
      generator.writeEndObject();
      generator.writeFieldName("phoneNumbers");
      generator.writeStartArray();
      generator.writeStartObject();
      generator.writeStringField("type", "home");
      generator.writeStringField("number", "310 555-1234");
      generator.writeEndObject();
      generator.writeStartObject();
      generator.writeStringField("type", "fax");
      generator.writeStringField("number", "310 555-4567");
      generator.writeEndObject();
      generator.writeEndArray();
      generator.writeEndObject();
      generator.close();
      out.println("person.json successfully generated");
   }
}
Listing A-20

Writing Numeric Values as Strings

Chapter 12: Processing JSON with JSON-P

  1. 1.

    JSON Processing (JSON-P) is a Java API for processing (i.e., parsing, generating, querying, and transforming) JSON content.

     
  2. 2.

    JSON-P 1.0 consists of 25 types located in package javax.json, along with the support packages javax.json.spi and javax.json.stream. The javax.json package mainly contains types that support the object model, the javax.json.spi package contains a single type that describes a service provider for JSON processing objects, and the javax.json.stream package contains types that support the streaming model.

     
  3. 3.

    The types for creating JsonArray and JsonObject models are JsonArrayBuilder and JsonObjectBuilder.

     
  4. 4.

    JSONValue is the superinterface of interface types that represent immutable JSON values.

     
  5. 5.

    JSON-P 1.1 differs from JSON-P 1.0 in that it supports JSON Pointer, JSON Patch, and JSON Merge Patch. Also, the new version adds editing and transformation operations to JSON array and object builders; and it also updates the API to better support Java SE 8 stream operations (including JSON-specific collectors).

     
  6. 6.

    The answer is false: JSON-P 1.0’s object model is more flexible than its streaming model.

     
  7. 7.

    You construct a JsonObject model by invoking Json’s createObjectBuilder() method to return a JsonObjectBuilder instance, invoking a chain of JsonObjectBuilder’s add() methods on this instance to add a hierarchy of objects, and invoking JsonObjectBuilder’s build() method on the builder instance to return a JsonObject that serves as the root of the tree.

     
  8. 8.

    The types that the streaming model provides to read and write JSON content are JsonParser and JsonGenerator.

     
  9. 9.

    JSON Merge Patch defines a JSON document structure for expressing a sequence of changes to be made to a target JSON document via a syntax that closely mimics that document. Recipients of a JSON Merge Patch document determine the exact set of changes being requested by comparing the content of the provided patch against the current content of the target document. If the patch contains members that don’t appear in the target, those members are added. If the target does contain the member, the value is replaced. Null values in the merge patch are given special meaning to indicate the removal of existing values in the target.

     
  10. 10.

    The editing/transformation operations that have been added to JsonArrayBuilder and JsonObjectBuilder are as follows: JsonArrayBuilder has received several add(int index, ...) methods for adding a value between array elements, several set(int index, ...) methods for updating an existing element, and a remove() method for removing an element. JsonObjectBuilder has received a remove() method for removing a name/value pair.

     
  11. 11.

    The answer is true: JSON-P 1.1 introduced a JsonCollectors class whose static collector methods return JSONObjects or JsonArrays instead of Maps or Lists.

     
  12. 12.

    Listing A-21 presents the JSONPDemo application that was called for in Chapter 12.

     
import java.io.FileReader;
import java.io.IOException;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonPointer;
import javax.json.JsonReader;
import static java.lang.System.*;
public class JSONPDemo
{
   public static void main(String[] args)
   {
      if (args.length != 2)
      {
         err.println("usage: java JSONPDemo jsonfile " +
                     "pointer");
         return;
      }
      try (var fr = new FileReader(args[0]))
      {
         JsonReader reader = Json.createReader(fr);
         JsonObject o = (JsonObject) reader.read();
         JsonPointer ptr = Json.createPointer(args[1]);
         out.println(ptr.getValue(o));
      }
      catch (IOException ioe)
      {
         err.printf("I/O error: %s%n", ioe.getMessage());
      }
   }
}
Listing A-21

Applying a JSON Pointer to a JSON Document

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.253.62