Use user input to search for a certain node in an xml using java

I have this xml code

I want to be able to have a scanner or some other object that asks for user input, then use that input to match a certain node and display that node and the rest under it.

For example, I want to have an option to search for either name, address, email, phone, or group. If i choose name, i want to be able to input the name "tim" then use that input to find the node and display it along with the sibling nodes, but only for that specific contact.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<contactInfo>
    <contact>
        <name>tim</name>
        <primary_address>1111 virginia road</primary_address>
        <secondary_address>N/A</secondary_address>
        <primary_email>[email protected]</primary_email>
        <backup_email1>N/A</backup_email1>
        <backup_email2>N/A</backup_email2>
        <primary_phone>703-111-1111</primary_phone>
        <backup_phone1>N/A</backup_phone1>
        <backup_phone2>N/A</backup_phone2>
        <group1>family</group1>
        <group2>friends</group2>
    </contact>
    <contact>
        <name>john</name>
        <primary_address>1111 pike road</primary_address>
        <secondary_address>N/A</secondary_address>
        <primary_email>[email protected]</primary_email>
        <backup_email1>N/A</backup_email1>
        <backup_email2>N/A</backup_email2>
        <primary_phone>222-222-2222</primary_phone>
        <backup_phone1>N/A</backup_phone1>
        <backup_phone2>N/A</backup_phone2>
        <group1>friends</group1>
        <group2>N/A</group2>
    </contact>
    <contact>
        <name>Tim Calara</name>
        <primary_address>1234 Wallaby Way</primary_address>
        <secondary_address>N/A</secondary_address>
        <primary_email>[email protected]</primary_email>
        <backup_email1>N/A</backup_email1>
        <backup_email2>N/A</backup_email2>
        <primary_phone>111-123-4567</primary_phone>
        <backup_phone1>N/A</backup_phone1>
        <backup_phone2>N/A</backup_phone2>
        <group1>family</group1>
        <group2>friends</group2>
    </contact>
   </contactInfo>

This is the search part of my code, let me know if you need my whole code (the whole this is lengthy).

public void search() throws SAXException, IOException, ParserConfigurationException, XPathExpressionException
{
    System.out.println("\nSearch for Contact");
    int choice = searchMenu ( );

    switch (choice)
    {
    case 1: 
        try 
        {

            File file = new File("/Users/T/Eclipse Workspace/contactInfo/nData.xml");
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document xmlDocument = dBuilder.parse(file);
            XPath xPath =  XPathFactory.newInstance().newXPath();

            System.out.println("Please enter Contact name: ");
            String input = kbd.nextLine();

            String expression = "/contactInfo/contact[name() = "input"]";
            System.out.println(expression);
            Node node = (Node) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODE);
            if(null != node) {
               NodeList nodeList = node.getChildNodes();
                for (int i = 0;null!=nodeList && i < nodeList.getLength(); i++) {
                    Node nod = nodeList.item(i);
                    if(nod.getNodeType() == Node.ELEMENT_NODE)
                        System.out.println(nodeList.item(i).getNodeName() + " : " + nod.getFirstChild().getNodeValue()); 
                }
            }


        } 
        catch (Exception e) 
        {
            e.printStackTrace();
        }
        break;

    //case 2:

    //case 3: email ( ); break;
    //case 4: phone ( ); break;
    //case 5: break;            
    //case 6: exit (); break;
        }       
}

Upvotes: 0

Views: 1293

Answers (3)

Nicolas Rinaudo
Nicolas Rinaudo

Reputation: 6168

The following example, will find the first element that contains a name child with a content of tim, and print the content of its name and primary_address elements:

Document doc   = getDocument();
XPath    xpath = XPathFactory.newInstance().newXPath();
NodeList nodeList;

nodeList = (NodeList) xpath.evaluate("//name[.='tim']/..", doc, XPathConstants.NODESET);
for(int i = 0; i < nodeList.getLength(); i++) {
    Node contact = nodeList.item(i);
    System.out.println("Name: " + ((Node)xpath.evaluate("name", contact, XPathConstants.NODE)).getTextContent());
    System.out.println("Address: " + ((Node)xpath.evaluate("primary_address", contact, XPathConstants.NODE)).getTextContent());
}

This is probably not the cleanest way of doing it, but it does the job. You can wrap most of it in helper methods - note how similar the two println statements are, they're just crying out for factorisation.

[EDIT] updated the example as requested in the comments

Upvotes: 0

Debojit Saikia
Debojit Saikia

Reputation: 10632

Here is how you can map your XML representation to Java classes with JAXB: In the given XML the ContactInfo element contains a list of contact child elements. If you represent ContactInfo and Conatct as Java objects, ContactInfo will contain a list of Contact instances.Below is a sample code to achieve this:

Create Contact class:

@XmlRootElement
public class Contact{
private String name;
private String primaryAddress;
//other properties
// getters and setters
}

And here is the ContactInfo class, which contains a list of Contact objects representing the contact elements of your XML file:

@XmlRootElement
public class ContactInfo {
private List<Contact> contactList;

public List<Contact> getContactList() {
    return contactList;
}

    @XmlElementWrapper(name = "ContactList")
    @XmlElement(name = "Contact")
    public void setCustomerList(List<Contact> contactList) {
        this.contactList =contactList;
    }
}

Now, by using JAXB you can read your xml file as follows:

File file = new File("Path to your xml file");
JAXBContext jaxbContext = JAXBContext.newInstance(ContactInfo.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
ContactInfo contactInfo = (ContactInfo) unmarshaller.unmarshal(file);

And you can also create your xml from ContactInfo as below:

//create your "ContactInfo" object with a list of "Contact"s
ContactInfo contactInfo=new ContactInfo();
List<Contact> list=new ArrayList<>();
//add contacts to the list and add the list to ContactInfo

File file = new File("path to save your XML file");
JAXBContext jaxbContext = JAXBContext.newInstance(ContactInfo.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(contactInfo, file);

I suggest you to read this : Java Architecture for XML Binding to get a good idea about the API.

Upvotes: 0

Ben Dale
Ben Dale

Reputation: 2572

Have you tried JAXB?

"Java Architecture for XML Binding (JAXB) allows Java developers to map Java classes to XML representations."

Then you could just iterate over objects.

http://en.wikipedia.org/wiki/Java_Architecture_for_XML_Binding

Upvotes: 1

Related Questions