/*
 *  SimpleDisplayXPath- find and print key and value tags in an XML document with DOM + Xpath
 *  Copyright (C) 2002  Ludovic MAITRE
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

import java.io.*;
import java.util.Properties;
import org.w3c.dom.*;
import org.w3c.dom.traversal.*;
import org.xml.sax.SAXException;
import org.xml.sax.InputSource;

// Imported JAVA API for XML Parsing 1.0 classes,
// Xerces implementation and XPath API
import org.apache.xerces.parsers.DOMParser;
import org.apache.xpath.XPathAPI;
import org.apache.xml.utils.TreeWalker;
import org.apache.xml.utils.DOMBuilder;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

// Imported Serializer classes
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;

import java.util.Hashtable;
import java.util.Enumeration;

public class SimpleDisplayXPath
{
    protected String filename = null;
    protected String xpath = null;
    static Hashtable hash;

    /** Process input args and execute the XPath.  */
    public void doMain(String[] args) throws Exception
    {
        filename = args[0];
        xpath = args[1];

        if ((filename != null) && (filename.length() > 0) &&
                (xpath != null) && (xpath.length() > 0))
        {
            System.out.println("Evaluating "+xpath);
            // Set up a DOM tree to query.
            InputSource in = new InputSource(new FileInputStream(filename));
            DocumentBuilderFactory dfactory =
                    DocumentBuilderFactory.newInstance();
            dfactory.setNamespaceAware(true);
            Document doc = dfactory.newDocumentBuilder().parse(in);

            // Set up an identity transformer to use as serializer.
            Transformer serializer =
                    TransformerFactory.newInstance().newTransformer();
            serializer.setOutputProperty(
                    OutputKeys.OMIT_XML_DECLARATION, "yes");

            // Use the simple XPath API to select a nodeIterator.
            NodeIterator all = XPathAPI.selectNodeIterator(doc, xpath);

            Node n;
            String key = null;
            String value = null;
            while ((n = all.nextNode()) != null)
            {
                //Ident(n);
                if (n.getNodeName().equals("key"))
                {
                    key = GetText(n);
                }
                else
                {
                    value = GetText(n);
                }
                if ((key != null) && (value != null))
                {
                    hash.put(key, value);
                    key = null;
                    value = null;
                }
            }
        }

    }

    private void Ident(Node n)
    {
        System.out.println("Name : "+n.getNodeName() + "\nType : "+
                n.getNodeType() + "\nVlue : "+n.getNodeValue());
    }

    static String GetText(Node n)
    {
        // DOM may have more than one node corresponding to a
        // single XPath text node.  Coalesce all contiguous text nodes
        // at this level
        StringBuffer sb = new StringBuffer();
        for (Node nn = n.getFirstChild(); isTextNode(nn);
                nn = nn.getNextSibling())
        {
            sb.append(nn.getNodeValue());
        }
        return sb.toString();
    }

    /** Decide if the node is text, and so must be handled specially */
    static boolean isTextNode(Node n)
    {
        if (n == null)
            return false;
        short nodeType = n.getNodeType();
        return nodeType == Node.CDATA_SECTION_NODE ||
                nodeType == Node.TEXT_NODE;
    }

    public SimpleDisplayXPath()
    {
        hash = new Hashtable();
    }
    /** Main method to run from the command line.    */
    public static void main (String[] args) throws Exception
    {
        if (args.length != 2)
        {
            System.out.println(
                    "java SimpleDisplayXPath filename.xml expressionxpath \n" +
                    "Lit le fichier et cherche l'expression xpath.");
            return;
        }
        long depart = System.currentTimeMillis();
        SimpleDisplayXPath app = new SimpleDisplayXPath();

        app.doMain(args);
        //Print the hashtable

        for (Enumeration e = hash.keys(); e.hasMoreElements();)
        {
            String key = (String) e.nextElement().toString();
            String value = (String) hash.get(key);
            System.out.println("key="+key + "; value="+value);
        }

        System.out.println("Temps :"+
                (System.currentTimeMillis() - depart));
    }

}

