Link to home
Start Free TrialLog in
Avatar of g46905
g46905

asked on

parsing through XML file and checking the validation

<?xml version="1.0" encoding="ISO-8859-1"?>
<Configuration>
   <Instance id="NNG" type="GAS">
      <profile name="Aquila" id="006966055">
        <dataflow option="abcdefault">
            <in id="NOMS"/>
                                 <in id="FNAK"/>
            <out id="NQRS"/>
            <out id="MVSO"/>
            <out id="SCHQ"/>
                <out id="OSQO"/>
         </dataflow>
       </profile>

      <profile name="BP Canada" id="248799413">
         <dataflow option="abcdefault">
            <out id="NQRS"/>
            <out id="SCHQ"/>
            <in id="NOMS"/>
            <in id="FNAK"/>
         </dataflow>
      </profile>

      <profile name="CIG1" id="006914865">
       <dataflow option="abcdefault">
                <in id="RFCI"/>
                <out id="CONO"/>
                <in id="FNAK"/>
         </dataflow>
       </profile>

      <profile name="Dynegy Gas Tran" id="137619136">
         <dataflow option="abcdefault">
            <in id="NOMS"/>
            <in id="FNAK"/>
            <out id="NQRS"/>
         </dataflow>
      </profile>
 </Instance>
</Configuration>
 
The user passes the profile name and the id (in or out) as the parameters. We should be able to check of the profile name exists and if yes, check if the id exists under that particular profile name.This is very important and I would really appreciate it if some expert can help me ASAP. Thanks in advance

Thanks,
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

I would use XPath. This comes with Java 1.5 or else you'll need an XPath library
Avatar of g46905
g46905

ASKER

I am new to XML translation and this needs to be done ASAP. Can you please help me with the code that is required to parse through the XML file and validate the parameters passed. I would really appreciate it.

Thanks,
Actually 1.4 has XPath too - it's just undocumented. Here's an example:

http://javaalmanac.com/egs/org.w3c.dom/xpath_GetAbsElem.html?l=new
The xpath would be

xpath = "//profile[@name='" + yourNameParam + " and @id='" + yourId + "']";  
hi G

You can use a DTD to validate the restrictions that you pose to your XML structure.
Go and read this good tutorial where you will get everything.

http://www.w3schools.com/dtd/default.asp

The good thing about DTD is that you can embed its reference in your XML itself and the DOM parser will validate automatically your XML against the DTD. So you don't have to program anything...
>>You can use a DTD to validate the restrictions ...

You seem to have misunderstood the question, but the use of the word 'validation' was perhaps a little misleading ;-)
hey hey ;)
Avatar of g46905

ASKER

I found the code which looks very similar to what I want. However, when I am trying to compile this, I am getting

Warning: Caught exception attempting to use SAX to load a SAX XMLReader
Warning: Exception was: org.xml.sax.SAXException: Can't create default XMLReader; is system property org.xml.sax.driver set?
Warning: I will print the stack trace then carry on using the default SAX parser
Warning: Error occurred using SAX to load a SAXParser. Will use Aelfred instead
org.xml.sax.SAXException: Can't create default XMLReader; is system property org.xml.sax.driver set?
      at org.xml.sax.helpers.XMLReaderFactory.createXMLReader(XMLReaderFactory.java:155)
      at org.dom4j.io.SAXHelper.createXMLReader(SAXHelper.java:67)
      at org.dom4j.io.SAXReader.createXMLReader(SAXReader.java:652)
      at org.dom4j.io.SAXReader.getXMLReader(SAXReader.java:527)
      at org.dom4j.io.SAXReader.read(SAXReader.java:313)
      at org.dom4j.io.SAXReader.read(SAXReader.java:224)
      at XmlParser.parse(XmlParser.java:25)
      at XmlParser.main(XmlParser.java:48)


import org.dom4j.*;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import java.io.*;
import java.util.*;
public class XmlParser {
      
      public Document parse(File file) throws DocumentException {
                  SAXReader reader = new SAXReader();
                  Document document = reader.read(file);
                  return document;
            }
   
         public void getValues(Document doc) throws Exception{
             Element root = doc.getRootElement();
         for ( Iterator i = root.elementIterator("Configuration"); i.hasNext(); ) {
                        Element matterElement = (Element) i.next();
           
       
                  for ( Iterator j = matterElement.attributeIterator(); j.hasNext(); ) {
                        Attribute attribute = (Attribute) j.next();
         
                    System.out.println(attribute.getValue());
                  }
            }
        }
 
        public static void main(String[] args){
         File f = new File("C:/Reporting/profilelistdir.xml");
         XmlParser obj = new XmlParser();
   
         try{
         Document d = obj.parse(f);
   
         obj.getValues(d);
        }catch(Exception e){
         e.printStackTrace();}

      }
      
}

Can some one please tell me what I am missing?

Thanks,

Strange, it's running fine for me. can you tow are you compiling this class and what jars you are using??
Avatar of g46905

ASKER

These are the external .jar file I have set up in the classpath and I am using WSAD as my IDE.Please let me know if you have any questions.Thanks a lot for your interest.

crimson-1.1.3-bin
dom4j-1.5-rc1.jar
dom.jar
jaxp-api.jar
jdom-b10
Xerces-J-bin.1.4.4
Xerces-J-bin.2.6.2
hey, although it is not giving me exception, but your program is not printing anything either. Although you might be expecting it to print the values youwant.
Avatar of g46905

ASKER

To be honest, I havent gone so far. I am still hanging to resolve this issue. I am stuck with this for a long time and I am afraid that I cannot meet the deadline if cannot resolve this by the end of the day. Can some please help me?

Thanks,
                   
Avatar of g46905

ASKER

I am using WSAD . I have read some suggestions for this similar problem and the solution is to put "org.xml.sax.driver=org.apache.xerces.parsers.SAXParser"  in a property file and make sure load it into your jvm:.I am not sure I to do this either.Please help

Thanks,
try this domparser, may be it will work on your comp.

import org.apache.xerces.parsers.DOMParser;

import org.w3c.dom.Node;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.NamedNodeMap;

public class Test1 {

 private static void printNode(Node node, String indent, int depth)  {

     switch (node.getNodeType()) {

         case Node.DOCUMENT_NODE:
             NodeList nodes = node.getChildNodes();
             if (nodes != null) {
                 for (int i=0; i<nodes.getLength(); i++) {
                     printNode(nodes.item(i), "", depth+1);
                 }
             }
             break;
             
         case Node.ELEMENT_NODE:
             String name = node.getNodeName();
             System.out.print(indent + "<" + depth+name);
             NamedNodeMap attributes = node.getAttributes();
             for (int i=0; i<attributes.getLength(); i++) {
                 Node current = attributes.item(i);
                 System.out.print(
                     " " + current.getNodeName() +
                     "=\"" + current.getNodeValue() +
                     "\"");
             }
             System.out.print(">");
             
             // recurse on each child
             NodeList children = node.getChildNodes();
             if (children != null) {
                 for (int i=0; i<children.getLength(); i++) {
                     printNode(children.item(i), indent + "  ",depth+1);
                 }
             }
             
             System.out.print("</" + name + ">");
             break;

         case Node.TEXT_NODE:
             System.out.print(node.getNodeValue());
             break;
     }

 }
 public static void main(String[] args) throws Exception{
         DOMParser parser = new DOMParser();
         parser.parse("c:/test/test.xml");
         Document doc = parser.getDocument();
         printNode(doc, "",-1);
 }

}
Avatar of g46905

ASKER

I am getting unable to resolve "import org.apache.xerces.parsers.DOMParser". I have both Xerces-J-bin.1.4.4 and
Xerces-J-bin.2.6.2 listed in the classpath. Please suggest.

Thanks for your help!
it sounds stupid, but are these Xerces-J-bin.2.6.2 jar files or what???

Actually there are jar files inside this package which you will need to include inside your classpath.
The only jar file you need is xercesImpl.jar
Heyy, about your earlier problem, have you tried this thing

System.setProperty("org.xml.sax.driver","org.apache.xerces.parsers.SAXParser");
Avatar of g46905

ASKER

I have tried it and it didn't work. Yes, Xerces-J-bin.2.6.2 is the latest version from apache. Let me try to add Xerces-J-bin.2.6.2 and see what happens.

Thanks,
Avatar of g46905

ASKER

Can you please suggest me a proper link where I can find the above mentioned xercesImpl.jar?

Thanks,
When you unzip the Xerces-J-bin.2.6.2.tar.gz or Xerces-J-bin.2.6.2.zip, in its lib directory, you will find this jar. Use winrar or winzip to unzip this.
Avatar of g46905

ASKER

Yes. You are right. I found it in the Xerces-J-bin.2.6.2.zip file. When I map the classpath to Xerces-J-bin.2.6.2.zip, shouldnt that be recognised?

Thanks,
Shekar
shekar,

classpath only recognizes jars and class files, and others like war, ear etc. whenever you download a package, you should always look for the jar files in it and include them in the path.

After you do this, you can import all java files that are there in these jars, into your program and use them.

btw, have you tried using System.getProperty also on your previous code.
The code I pasted will also give you the depth of each node. It will just give greater control over your xml parsing. Hope now your program will run without error :)
Avatar of g46905

ASKER

I have pointed the class path to xercesImpl.jar and I dont see the error at this moment. As you mentioned earlier, I dont see any output either.Atleast, this gives me lot of relief as we were woprking on this since morning. I will get bakc to you tonight. I really appreciate all your patience and help. Thanks buddy.
You're wlcm :)
and don't forget to change the xml file path ;-)
As i mentioned earlier, the easiest way to do this is with XPath. This works fine for me with your xml:

import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;

/**
 *  Validate a 'profile' using XPath
 *
 * @author     CEHJ
 * @created    13 August 2004
 */
public class Profile {

      public static void main(String[] args) {
            // Command line arguments : file name, name, id
            // e.g. "profile.xml CIG1 006914865"
            System.out.println(validUser(args[0], args[1], args[2]));
      }


      // Parses an XML file and returns a DOM document.
      // If validating is true, the contents is validated against the DTD
      // specified in the file.

      public static Document parseXmlFile(String filename, boolean validating) {
            try {
                  // Create a builder factory
                  DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                  factory.setValidating(validating);

                  // Create the builder and parse the file
                  Document doc = factory.newDocumentBuilder().parse(new File(filename));
                  return doc;
            }
            catch (Exception e) {
                  e.printStackTrace();
                  return null;
            }
      }

      public static boolean validUser(String fileName, String name, String id) {
            Document doc = parseXmlFile(fileName, false);
            NodeList nodelist = null;
            boolean valid = false;
            try {
                  // Get the matching elements
                  String xpath = "//profile[@name='" + name + "' and @id='" + id + "']";
                  //System.out.println("xpath=" + xpath);
                  nodelist = org.apache.xpath.XPathAPI.selectNodeList(doc, xpath);
                  valid = (nodelist != null && nodelist.getLength() > 0);
            }
            catch (javax.xml.transform.TransformerException e) {
                  e.printStackTrace();
                  return false;
            }
            return valid;
      }
}

Avatar of g46905

ASKER

CEHJ,
       As you mentioned, I was thinkng  of the option of using the Xpath, but when I try to compile it, this is what I see

org.apache.xpath.XPathAPI cannot be resolved.

Can you please suggest me if I have to add any missing package?

Thanks,

Avatar of g46905

ASKER

CEHJ,
       I downloaded the Xalan.jar and not getting any compiling errors. I am currently working on the code to see if it serves the purpose. I shall let you know about the result. Thanks for your help.

Thanks again,
Avatar of g46905

ASKER

CEHJ,      
        <profile name="CIG1" id="006914865">
       <dataflow option="nngdefault">
                <in id="RFCI"/>
                <out id="CONO"/>
                <in id="FNAK"/>
         </dataflow>
       </profile>

As I metioned earlier, the user enters the profile name and the id (for Example RFCI or CONO) which is the attribute value for in or out and I will have to make sure it is under the given profile (for example CIG1 in your code) and return the value. Can you please help me with the modification of the code?

Thanks
>>Can you please suggest me if I have to add any missing package?

You should update your Java to >= 1.4 if you can rather than use additional libraries. If you're using a version < 1.4 you're missing out on a lot of library functionality

>>and return the value

What value do you mean?
If you mean the profile node in question, just make the method i gave you return Node instead of boolean:


public static Node validUser(String fileName, String name, String id) {

.....

    return valid?  nodelist.item(0) : null;

.....
}
Avatar of g46905

ASKER

CEHJ,
        My Question is the id (ie for example RFCI or CONO) that I enter needs to be checked that it falls under the profile entered and then return the ture or false value. Please let me know if its not clear.

Thanks,
OK - got it - hang on ...
SOLUTION
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of g46905

ASKER

kumvjuec,
              The code what you sent suites my requirement. I made some changes to the code (main class) so that it can be called from another class by passing the required parameters and used SAXException as you can see below.I get the message

SAXException cannot be resolved.

Can you please tell me how to resolve this issue.




public static boolean checkValidTp (String xmlFileName,String profile,String id_in_out )throws SAXException{
                //0 = xml, 1 = profilename, 2 = idval
               
        try{        
       
         DOMParser parser = new DOMParser();
         parser.parse(xmlFileName);
         Document doc = parser.getDocument();
         found = false;
         printNode(doc, "",-1,id_in_out,profile);
           if (found == true)
              System.out.println("Yes, match found");
         else
              System.out.println("Nopes, no match");
             
      return found;
      
                
 }

Thanks a lot!
Can you tell me what is not 'suitable' about the code i posted g46905? XPath is specifically designed for the sort of purposes you need
...and the (tested) code i posted works fine for your purpose, unless in some way i've misunderstood what you want
Avatar of g46905

ASKER

CEHJ,
       I code that you posted works fine and gives me the expected result and I really appreciate your help. Now, I have been asked to buid a code where I need to add some more methods. I am trying to create an XML class by extending the current class( from where the XML class is being called) that I have written. This XML class should be capable to parse through the XML file with these additional features

forExample:

public static String getDunsNumber(String profile){

// for example profile = CIG1

This method should store all the values( if profile = CIG1, then 006914865) in the hash table so that I can use the hash table to print all the values in my final report.

}

public Static boolean checkValidUser( String profile,String id){

// e.g. "CIG1 CONO"


This should do the samething what your code does

}


public Static String getDirection(String profile,String id){

// e.g. profile = CIG1, id =  CONO"

This should return "out" // since <out id="CONO"/>

}

This is what I desire my code to do. Since , I am not familiar with Xpath, I was't sure how much effort it would take.If you think this can be done very ealisy , I will be glad to use it. Please give me your valuable suggestion.

Thanks again for all your help and concern.





Well the point about XPath is that it is extensible for doing exactly the sort of thing that you need.

These three methods seem to be quite related. The point about what i said earlier about returning the Node instead of a boolean value is that all the information of the valid Node would already be in the Node. There's no need to store it in a structure (if that's what you're proposing with getDunsNumber) - it's *already* stored in a structure
Avatar of g46905

ASKER

since I am new to Xpath, Can you please help with the above metioned methods that I suggested.I am running out of time and this is very important.

Thanks a lot
Avatar of g46905

ASKER

kumvjuec,
              I tried to run the code that you sent me at my office pc which has WSAD installed and it worked fine.But,when I am running the same at my home PC, I am getting this error.Can you please tell me what might have been the problem.

java.net.MalformedURLException: no protocol: profiletest.xml
      at java.net.URL.<init>(URL.java:500)
      at java.net.URL.<init>(URL.java:403)
      at java.net.URL.<init>(URL.java:357)
      at org.apache.xerces.impl.XMLEntityManager.startEntity(XMLEntityManager.java:807)
      at org.apache.xerces.impl.XMLEntityManager.startDocumentEntity(XMLEntityManager.java:753)
      at org.apache.xerces.impl.XMLDocumentScannerImpl.setInputSource(XMLDocumentScannerImpl.java:260)
      at org.apache.xerces.parsers.DTDConfiguration.parse(DTDConfiguration.java:499)
      at org.apache.xerces.parsers.DTDConfiguration.parse(DTDConfiguration.java:581)
      at org.apache.xerces.parsers.XMLParser.parse(XMLParser.java:152)
      at org.apache.xerces.parsers.DOMParser.parse(DOMParser.java:191)
      at Test1.main(Test1.java:77)
Exception in thread "main"

Thanks a lot
Avatar of g46905

ASKER

I found the solution for the above mentioned question and it worked fine. Here is what I found

DOS filenames are not legal URIs as required by the XML 1.0 specification. Therefore, it was an error for the parser to accept DOS filenames. This bug is now fixed.

DOS filenames can be converted to legal URLs, however. For example, the DOS filename "c:\xerces\data\personal.xml" would become "file:///c:/xerces/data/personal.xml", which is a legal URL.

Thanks,
Avatar of g46905

ASKER

CEHJ,
        I am given some more time and hence decided to go with Xpath model that you send me.Here is what I am trying

How do I return the value of a given attribute?

Please help.

Thanks,
hi g,

Sorry, I was away for sometime...
Thanks for the points. :)
I would say that though XPATH api is very friendly and easy to use, still for performance reasons, one has to be very careful with it.
For the example above by cehj, "//" has been used in the XPATH which is really very errorprone if you are not careful about putting the node at some correct place at correct depth in the document.
In my code, such errors will not arise.

If you want to get the value of attribute for XPATH then use this
"/checkIn/@bug" is the XPATH for getting the attribute value in this XML

<checkIn bug="1111111">
  <regression>
  </regression>
</checkIn>

About the MALFormedURLException
have you checked if the filename and path you are specifying is correctly formed or not??

Hope that helps solve some of your problems :)
If you are trying to form a URL, then you must have file:// or http:// or ftp:// or something like that in the start of the string that you are trying to convert. These prefixes specify the protocol which must be used to communicate with the url.
:-)

The easiest way, for the file/url thing, if there's any doubt


File f = ...

URL url = f.toURL();
Avatar of g46905

ASKER

kumvjuec,
              I am having hard time with boss as he comes up with different specs day by day  and I need to be flexible to make the necessary adjustments (to keep my job :-)). Now he wants to have an option of generating multiple profiles at the sane time.

while passing the parameter profile, He would like to pass a string "CIG1,BP Canada,and so on". I need to brak this to each single profile and check if it exists. Can you please help me with the modifications required so that i can check multiple profiles at same time?

Thanks,
Avatar of g46905

ASKER

kumvjuec,
              I made changes to the code you mentioned. It is being called from another class.How do I come out of the printNode() methis as soon as the found value becomes true?

Please suggest .

Thanks,
For the case where you need to check only one node, you can insert a statement on the top of the printNode method

if (found)
  return;

There will be no more recursion and it will come out of printNode()

About your earlier query, i'll post soon
Use this with appropriate changes for xml path etc

package vj.org.all;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.apache.xerces.parsers.DOMParser;

import org.w3c.dom.Node;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.NamedNodeMap;

public class Test1 {
      private static boolean[] found = null;
      public static void setFound(int n)
      {
            found = new boolean[n];
            for (int i=0; i<n; i++)
                  found[i] = false;
      }

 private static void printNode(Node node, String indent, int depth, List idval, List profilename)  {

     switch (node.getNodeType()) {

         case Node.DOCUMENT_NODE:
             NodeList nodes = node.getChildNodes();
             if (nodes != null) {
                 for (int i=0; i<nodes.getLength(); i++) {
                     printNode(nodes.item(i), "", depth+1,idval,profilename);
                 }
             }
             break;
             
         case Node.ELEMENT_NODE:
             String name = node.getNodeName();
             NamedNodeMap attributes = node.getAttributes();
             for (int i=0; i<attributes.getLength(); i++) {
                 Node current = attributes.item(i);
                 
                 for (int k=0; k<idval.size(); k++) {      //Inserted
                 if (current.getNodeName().equals("id") && 
                       (name.equals("in") || name.equals("out")) &&
                              (current.getNodeValue().equals((String)idval.get(k))))
                 {
                       Node profilenode = node.getParentNode().getParentNode();
                       NamedNodeMap profileattr = profilenode.getAttributes();
                       for (int j=0; j<profileattr.getLength(); j++)
                       {
                             if (profileattr.item(j).getNodeName().equals("name"))
                             {
                                   if (profileattr.item(j).getNodeValue().equals((String)profilename.get(k)))
                                   {
                                         found[k] = true;
                                         return;
                                   }
                             }
                       }
                 }
             }
             }//Inserted
             
             // recurse on each child
             NodeList children = node.getChildNodes();
             if (children != null) {
                 for (int i=0; i<children.getLength(); i++) {
                     printNode(children.item(i), indent + "  ",depth+1,idval,profilename);
                 }
             }
             
             break;

         case Node.TEXT_NODE:
             break;
     }
     
 }


 /**
  * Sole entry point to the class and application.
  * @param args Array of String arguments.
  */
 public static void main(String[] args) throws Exception{
                   //0 = xml, 1 = profilename, 2 = idval
         DOMParser parser = new DOMParser();
         parser.parse("c:/test/test.xml");
         Document doc = parser.getDocument();
         
         
         //Get individual arguments
         List id = new ArrayList();
         List name = new ArrayList();
         StringTokenizer st = new StringTokenizer("NQRS,Aquila,id2,name2",",");
         int i=0;
         while (st.hasMoreTokens())
         {
               id.add(st.nextElement());
                  name.add(st.nextElement());
                  i++;
         }
         setFound(i);
         printNode(doc,"",-1,id,name);
         //printNode(doc, "",-1,args[2],args[1]);
         for (int j=0; j<i; j++)
         {
         if (found[j] == true)
               System.out.println("Yes, match found for "+(String)name.get(j));
         else
               System.out.println("Nopes, no match for "+(String)name.get(j));
         }
 }

}
Also, you can use error checks like there are id, name in PAIRS witout extra spaces and you can use your custom delimitor while you initialize StringTokenizer
>>
For the example above by cehj, "//" has been used in the XPATH which is really very errorprone if you are not careful about putting the node at some correct place at correct depth in the document.
>>

That's effectively FUD i'm afraid. g46905 wants to check all profile nodes at any depth for matching attributes. That's precisely the xpath that does that

>>In my code, such errors will not arise.

Please show which code (preferably by url) you are referring to and explain why

Incidentally g46905, once the dust has settled a bit, you should really use a DTD or schema for your xml
Avatar of g46905

ASKER

Thankyou both for your valueble suggestions. I will get back to you reagarding this if I come across any more issues.

Have a good one folks.
Avatar of g46905

ASKER

I got done with my XML issue as I was able to get the desired parsing result. I sincerely thanks you both for all the support.

Thanks again,
wlcm :)
:-)