7/9/08


Java and XML: query over XML

There is not included API for XQuery in Java 5 or 6. There is not included XPath API in Java till 5. But in java 5 and higher there is facilities for addressing element or group of elements via XPath. Probably in Java 7 it will be realized (XQJ or JSR 225 - like JDBC). Any case SUN is not only vendor of such kind of API.

XPath with Saxon
SAXON is the XSLT and XQuery Processor. Most XSLT and XQuery functionality in Saxon will work without installing JAXP 1.3.

import net.sf.saxon.dom.DOMNodeList;
import net.sf.saxon.om.NamespaceConstant;
import net.sf.saxon.om.NodeInfo;
import net.sf.saxon.xpath.XPathEvaluator;
import org.xml.sax.InputSource;
import javax.xml.namespace.NamespaceContext;
import javax.xml.transform.sax.SAXSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import java.io.FileInputStream;
import java.util.Iterator;
import net.sf.saxon.dom.ElementOverNodeInfo;

public class XPathExample implements NamespaceContext {

 public static void main (String args[]) throws Exception {
  System.setProperty("javax.xml.xpath.XPathFactory:"+NamespaceConstant.OBJECT_MODEL_SAXON, "net.sf.saxon.xpath.XPathFactoryImpl");
  XPathFactory xpf = XPathFactory.newInstance(NamespaceConstant.OBJECT_MODEL_SAXON);
  XPath xpe = xpf.newXPath();
  InputSource is = new InputSource(new FileInputStream("D:/dev/Temp_java/src/com/PhoneBook.xml"));
  SAXSource ss = new SAXSource(is);
  NodeInfo doc = ((XPathEvaluator)xpe).setSource(ss);
  XPathExpression findLine = xpe.compile("/*[1]/*[1]");
  DOMNodeList matchedLines = (DOMNodeList)findLine.evaluate(doc, XPathConstants.NODESET) ;
  if (matchedLines != null) {
   for (int i = 0; i < matchedLines.getLength(); i++) {
    ElementOverNodeInfo info =((ElementOverNodeInfo)matchedLines.item(i));
    System.out.println(info.getTextContent());
   }
  }
 }

 public String getNamespaceURI(String prefix) {
  return null;
 }
 public String getPrefix(String namespaceURI) {
  return null;
 }
 public Iterator getPrefixes(String namespaceURI) {
  return null;
 }
}

Result:

0
Alex
Kuiv, Kominterna 28
aillusions@gmail.com
+380664392825


XPath with JAXP 1.3
JAXP is the Java API for XML Processing. In version SE 1.5 it included by default but there is version JAXP 1.3 for JDK 1.4 (by default has JAXP 1.1). To use this API in 1.4 property -Djava.endorsed.dirs=DIR_WITH_JAXP1.3_JARS should be set, or copy all of the jar files except jaxp-api.jar into /jre/lib/endorsed.

import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Iterator;

import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

public class XPathDemo {

 public static void main(String[] args) throws Exception {

  String xmlFile = "D:/dev/Temp_java/src/com/PhoneBook.xml";
  String xpathExpression = "/*/pb:BookRecord/pb:id";

  XPathFactory xpf = XPathFactory.newInstance();
  XPath xpath = xpf.newXPath();

  NamespaceContextImpl namespaceContextImpl = new NamespaceContextImpl();
  namespaceContextImpl.bindPrefixToNamespaceURI("pb","http://www.epam.com/com/PhoneBook");

  xpath.setNamespaceContext(namespaceContextImpl);
  FileInputStream saxStream = new FileInputStream(xmlFile);
  NodeList saxNodeList = null;
  saxNodeList = (NodeList)xpath.evaluate(xpathExpression, new InputSource(saxStream), XPathConstants.NODESET);

  for (int i = 0; i < saxNodeList.getLength(); i++) {
   System.out.println(" name: " + saxNodeList.item(i).getNodeName()+", value: " + saxNodeList.item(i).getNodeValue());
  }
 }
}

class NamespaceContextImpl implements NamespaceContext {

 private HashMap prefixToNamespaceURI = new HashMap();
 private HashMap namespaceURIToPrefix = new HashMap();

 public void bindPrefixToNamespaceURI(String prefix, String namespaceURI) {
  prefixToNamespaceURI.put(prefix, namespaceURI);
  namespaceURIToPrefix.put(namespaceURI, prefix);
 }

 public String getNamespaceURI(String prefix) {
  if (prefixToNamespaceURI.containsKey(prefix))
   return (String)prefixToNamespaceURI.get(prefix);
  return XMLConstants.NULL_NS_URI;
 }

 public String getPrefix(String namespaceURI) {
  if (namespaceURIToPrefix.containsKey(namespaceURI))
   return (String)namespaceURIToPrefix.get(namespaceURI);
  return null;
 }

 public Iterator getPrefixes(String namespaceURI) {
  throw new UnsupportedOperationException("NamespaceContextImpl#getPrefixes(String namespaceURI) not implemented");
 }
}

And result:

name: pb:id, value: null
name: pb:id, value: null
name: pb:id, value: null


XPath with Jaxen
Jaxen is able to interact with DOM, Dom4j and JDOM.

import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.jaxen.dom.DOMXPath;
import org.jaxen.XPath;
import java.util.List;
import java.util.Iterator;

public class Main {

 public static void main(String argv[]) throws Exception {
  DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  factory.setNamespaceAware(true);

  Document doc = factory.newDocumentBuilder().parse("D:/dev/Temp_java/src/com/PhoneBook.xml");
  XPath xpath = new DOMXPath("//pb:id");
  xpath.addNamespace("pb", "http://www.epam.com/com/PhoneBook");
  xpath.addNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");

  List results = xpath.selectNodes(doc);
  Iterator resultIter = results.iterator();

  while(resultIter.hasNext()){
   System.out.println( resultIter.next());
  }
 }
}

As result:

<pb:id>0</pb:id>
<pb:id>1</pb:id>
<pb:id>2</pb:id>


XPath with SAXPath
SAXPath has been merged into the Jaxen codebase and is no longer being maintained separately.

XPath with Xalan
Xalan-Java is an XSLT processor for transforming XML documents: http://xml.apache.org/xalan-j. Xalan includes the JAXP packages, implements the TrAX portion of that API (javax.xml.transform....), implements the XPath API of JAXP (javax.xml.xpath....), and includes xercesImpl.jar from Xerces-Java 2.9.0, which implements the parser portion of the API (javax.xml.parser....).

import java.io.FileInputStream;
import java.io.OutputStreamWriter;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.xpath.XPathAPI;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.traversal.NodeIterator;
import org.xml.sax.InputSource;

public class ApplyXPath {

 public static void main(String[] args) throws Exception {

  String filename = "D:/dev/Temp_java/src/com/PhoneBook.xml";
  String xpath = "/*[1]/*[1]";

  InputSource in = new InputSource(new FileInputStream(filename));
  DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
  dfactory.setNamespaceAware(true);
  Document doc = dfactory.newDocumentBuilder().parse(in);
  Transformer serializer = TransformerFactory.newInstance().newTransformer();
  serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");

  NodeIterator nl = XPathAPI.selectNodeIterator(doc, xpath);

  Node n;
  while ((n = nl.nextNode()) != null) {
   serializer.transform(new DOMSource(n), new StreamResult(new OutputStreamWriter(System.out)));
  }
 }
}

Result:

<pb:BookRecord xmlns:pb="http://www.epam.com/com/PhoneBook" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <pb:id>0</pb:id>
  <pb:name>Alex</pb:name>
  <pb:address>Kuiv, Kominterna 28</pb:address>
  <pb:email>aillusions@gmail.com</pb:email>
  <pb:phone>+380664392825</pb:phone>
 </pb:BookRecord>

Java and XML: transformation XML

We can process our xml with code:

import java.io.File;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

public class Main {

 public static void main(String argv[]) throws Exception {
  File xmlFile = new File("src/com/PhoneBook.xml");
  File xsltFile = new File("src/com/PhoneBook.xsl");
  TransformerFactory transFact = TransformerFactory.newInstance();
  Transformer trans = transFact.newTransformer(new StreamSource(xsltFile));
  trans.transform(new StreamSource(xmlFile), new StreamResult(System.out));
 }
}

And result:

<?xml version="1.0" encoding="UTF-8"?>
<strong>Value</strong>

Java and XML: parsing XML

SAX - simple API for XML processing:

SAXParser saxParser = SAXParserFactory.newInstance().newSAXPar\ser();
saxParser.parse(new ByteArrayInputStream("<aaa>bbb</aaa>".getBytes()), new DefaultHandler());

Above is simplest sample. Now I am going to show parsing with validation by SAX.
Let's create simple SAX parser handler:

class PhoneBookHandler extends DefaultHandler{
 public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
  System.out.println(localName);
  super.startElement(uri, localName, name, attributes);
 }
 public void error(SAXParseException e) throws SAXException {
  e.printStackTrace();
  super.error(e);
 }

And main code:

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.helpers.DefaultHandler;

public class Main {
 public static void main(String argv[]) throws Exception {
  SAXParserFactory pf = SAXParserFactory.newInstance();
  pf.setNamespaceAware(true);
  pf.setValidating(true);
  SAXParser p = pf.newSAXParser();
  p.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
  p.parse("D:/dev/Temp_java/src/com/PhoneBook.xml", new PhoneBookHandler());
 }
}

If you do not have schemaLocation in your xml file, you can define schema location in parser property:

p.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource", new File("%PATH_TO_YOUR_XSD%/PhoneBook.xsd"));

schemaSource property in parser is more important than schemaLocation in xml instance.

DOM - document object model

import javax.xml.parsers.*;
...
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse("D:/dev/Temp_java/src/com/xml.xml"); System.out.println(doc.getElementsByTagName("Record").item(0).getFirstChild().getNextSibling());

JDOM - java-oriented (not XML) representation of an XML document
JDOM is the Java-based solution for accessing, manipulating, and outputting XML data from Java code. It corresponds JSR-102 - API for easy and efficient reading, manipulation, and writing of XML documents and XML data.

SAXBuilder builder = new SAXBuilder();
Document doc = builder.build("D:/dev/Temp_java/src/com/PhoneBook.xml");
System.out.println(doc.getRootElement().getChildren().get(0).toString());

StAX - Streaming API for XML
JSR 173 defines a pull streaming model, StAX (short for "Streaming API for XML"), for processing XML documents. In this model, unlike in SAX, the client can start, proceed, pause, and resume the parsing process. The client has complete control.
A StAX Implementation:
- Sun's Implementation - SJSXP
- BEA Reference Implementation
- WoodSToX XML Processor
- Oracle StAX Pull Parser Preview
- Codehaus StAX
Sun Java Streaming XML Parser - SJSXP - is an implementation of the StAX API. We need sjsxp.jar and jsr173_1.0_api.jar in class path

import java.io.FileInputStream;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamReader;

public class Main {

 public static void main(String argv[]) throws Exception {
  FileInputStream fileInputStream = new FileInputStream("D:/dev/Temp_java/src/com/PhoneBook.xml");
  XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(fileInputStream);

  while (true) {
   int event = xmlStreamReader.next();
   if (event == XMLStreamConstants.END_DOCUMENT) {
    xmlStreamReader.close();
    break;
   }
   if (event == XMLStreamConstants.START_ELEMENT) {
    System.out.println(xmlStreamReader.getLocalName());
   }
  }
 }
}

Result:

PhoneBook
BookRecord
id
name
address
email
phone
BookRecord
id
name
address
email
phone
BookRecord
id
name
address
email
phone

Apache Axiom - AXis Object Model - the XML object model that uses StAX as its underlying XML parsing methodology.
XML infoset refers to the information included inside the XML, and for programmatic manipulation it is convenient to have a representation of this XML infoset in a language specific manner. For an object oriented language the obvious choice is a model made up of objects. DOM and JDOM are two such XML models. Axiom is too, but it uses "pull parsing" - a recent trend in XML processing. Axiom is based on StAX (JSR 173 ), which is the standard streaming pull parser API. Axiom needs JAXP 1.3 so java 5 should be used, or -Djava.endorsed.dirs=D:/env/xml/jaxp-1_3 should be set.

import java.io.FileInputStream;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;

public class Main {

 public static void main(String argv[]) throws Exception {
  String xmlFName = "D:/dev/Temp_java/src/com/PhoneBook.xml";

  XMLStreamReader parser = XMLInputFactory.newInstance().createXMLStreamReader(new FileInputStream(xmlFName));
  StAXOMBuilder builder = new StAXOMBuilder(parser);
  OMElement documentElement = builder.getDocumentElement();
  System.out.println(documentElement.getChildElements().next());
 }
}

Xerces - Apache parsers that supports standard APIs - most popular SAX and DOM parser.
Xerces is a family of software packages for parsing and manipulating XML, it provides both XML parsing and generation.
Creating a DOM Parser:

import org.apache.xerces.parsers.DOMParser;
import org.w3c.dom.Document;

public class Main {

 public static void main(String argv[]) throws Exception {
  String xmlFile = "D:/dev/Temp_java/src/com/PhoneBook.xml";
  DOMParser parser = new DOMParser();
  parser.parse(xmlFile);
  Document document = parser.getDocument();
  System.out.println(document.getChildNodes().item(0).getNodeName());
 }
}

Result:

pb:PhoneBook

Creating a SAX Parser:

import org.xml.sax.AttributeList;
import org.xml.sax.DocumentHandler;
import org.xml.sax.Locator;
import org.xml.sax.Parser;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.ParserFactory;

public class Main implements DocumentHandler {

 public static void main(String argv[]) throws Exception {
  String xmlFile = "D:/dev/Temp_java/src/com/PhoneBook.xml";
  String parserClass = "org.apache.xerces.parsers.SAXParser";
  Parser parser = ParserFactory.makeParser(parserClass);
  parser.setDocumentHandler(new Main());
  parser.parse(xmlFile);
 }

 public void characters(char[] ch, int start, int length) throws SAXException {}
 public void endDocument() throws SAXException {}
 public void endElement(String name) throws SAXException {}
 public void ignorableWhitespace(char[] ch, int start, int length){}
 public void processingInstruction(String target, String data)throws SAXException {}
 public void setDocumentLocator(Locator locator) {}
 public void startDocument() throws SAXException {}
 public void startElement(String name, AttributeList atts) throws SAXException {
  System.out.println(name);
 }
}

Result:

pb:PhoneBook
pb:BookRecord
pb:id
pb:name
pb:address
pb:email
pb:phone
pb:BookRecord
pb:id
pb:name
pb:address
pb:email
pb:phone
pb:BookRecord
pb:id
pb:name
pb:address
pb:email
pb:phone

Crimson XML – A faster SAX and DOM parser
...
Sparta XML – A fast and small SAX and DOM parser also includes an XPath subset
...
StelsXML is a JDBC type 4 driver that allows to perform SQL queries and other JDBC operations on XML files
...

7/2/08


Java and XML: intro

Let's consider PhoneBook.xml:

<?xml version="1.0"?>
<pb:PhoneBook xmlns:pb="http://www.epam.com/com/PhoneBook" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.epam.com/com/PhoneBook PhoneBook.xsd">
 <pb:BookRecord>
  <pb:id>0</pb:id>
  <pb:name>Alex</pb:name>
  <pb:address>Kuiv, Kominterna 28</pb:address>
  <pb:email>aillusions@gmail.com</pb:email>
  <pb:phone>+380664392111</pb:phone>
 </pb:BookRecord>
 <pb:BookRecord>
  <pb:id>1</pb:id>
  <pb:name>Zhanna</pb:name>
  <pb:address>Kuiv, Showkunenko 3</pb:address>
  <pb:email>estetka@mail.ru</pb:email>
  <pb:phone>+380666464111</pb:phone>
 </pb:BookRecord>
</pb:PhoneBook>

xsd file PhoneBook.xsd:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.epam.com/com/PhoneBook" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <xsd:element name="PhoneBook">
  <xsd:complexType>
   <xsd:sequence minOccurs="0" maxOccurs="unbounded">
    <xsd:element name="BookRecord">
     <xsd:complexType>
      <xsd:sequence minOccurs="0">
       <xsd:element type="xsd:int" name="id" />
       <xsd:element type="xsd:string" name="name" />
       <xsd:element type="xsd:string" name="address" />
       <xsd:element type="xsd:string" name="email" />
       <xsd:element type="xsd:string" name="phone" />
      </xsd:sequence>
     </xsd:complexType>
    </xsd:element>
   </xsd:sequence>
  </xsd:complexType>
 </xsd:element>
</xsd:schema>

xsl file PhoneBook.xsl:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="/">
  <strong>
   <xsl:text>Value</xsl:text>
  </strong>
 </xsl:template>
</xsl:stylesheet>

6/27/08


What new in j2se 1.5.0

- added in java.util.Arrays static toString() method
- added generics
- hot swap realised
- added StringBuilder. It is identical to StringBuffer except that it is not synchronized. In single-threaded programs StringBuilder is slightly faster.
- added XML validation package at javax.xml.validation and the XPath libraries at javax.xml.xpath
- added annotation

6/18/08


Programming Ideas

There are a lot of obstruction on the way of new programmer. If he or she is newbie and does not have access to real development process it means he or she does not have access to best practice and up-to-date knowledges about technologies, tools, approaches etc. But most substantial issue is lack interesting and useful task for practice and develop skills. So I have one proposal as choice to resolve that problem: be imitator.
Yeah. Just try to copy existing well knowing functionality or application. It is not new idea, I know, but it is not so obvious to use this method in every day. I have seen movie about some painter who trained to draw by copy another's picture. Let's contrive some examples:
- Calc
- Excel
- Lingvo
- TotalCommander
- Bizarre
- BlogSpot
- Eclipse
- gmail
- forum
- CMS
- game ..
Or only functionality:
- Java collection implementation
- Java ORM implementation
- java.lang.String implementation

And also some notes:

//---------------
System.out.println( new SimpleDateFormat("yyyy-MMM-dd hh:mm:ss").format(new Date()));
System.out.println( new SimpleDateFormat("yyyy-MMM-dd (E) hh:mm:ss [z]", Locale.ENGLISH).parse("2008-Jun-27 (Fri) 01:18:46 [EEST]"));
//---------------
new StringBuilder("qwerty").reverse().toString();
//---------------
public enum Status {
Open("O"), Closed("C"), Reopened("R");
final String code;
Status(String code) {
this.code = code;
}
}
//---------------

6/3/08


Web Service Development

JAX-RPC is a Java community effort to eliminate problems with Web service implementations and provide a well-known application programming interface (API) on both the client and the server side. JAX-RPC provides an easy to develop programming model for development of SOAP based Web services.

So in details: JAX-RPC (java API for XML based RPC) is the API specification for J2EE 1.4 and presented as RFC 101. SUN (in WSDP) and Apache (in AXIS) have its own implementation that API. JAX-RPC defines API for creating SEI (service end point) and client endpoint. JAX-RPC enables a Web service endpoint to be developed using either a Java Servlet or Enterprise JavaBeans (EJB) component model (JSR 109). A Web service endpoint is deployed on either the Web container or EJB container based on the corresponding component model.
(I mean JAX-RPC 1.1.)
The latest version of JAX-RPC is 2.0. But it has new name: JAX-WS 2.0 - JSR-224. JAX-WS programming model is JavaEE5 compliant.
EJB3 stateless session bean - JAX-WS.
EJB-2.1 stateless session bean - JAX-RPC.

A JAX-RPC client can use stubs-based, dynamic proxy or dynamic invocation interface (DII) programming models to invoke a heterogeneous Web service endpoint. JAX-RPC uses SAAJ API for SOAP message handlers.

Using wscompile from WSDP toolkit made by SUN:

wscompile.bat -classpath build/classes -gen:server -f:rpcliteral config.xml -d build/classes -nd WebContent/WEB-INF/wsdl -mapping WebContent/WEB-INF/mapping.xml

-d directory to put generated and compiled classes
-nd directory to put "non classes" generated stuff (wsdl etc.)