1

i have an xml file that contains lots of different nodes. some in particularly are nested like this:

 <emailAddresses>
            <emailAddress>
                <value>[email protected]</value>
                <typeSource>WORK</typeSource>
                <typeUser></typeUser>
                <primary>false</primary>
            </emailAddress>
            <emailAddress>
                <value>[email protected]</value>
                <typeSource>HOME</typeSource>
                <typeUser></typeUser>
                <primary>true</primary>
            </emailAddress>
        </emailAddresses>

From the above node, what i want to do is go through each and get the values inside it(value, typeSource, typeUser etc) and put them in a POJO.

i tried to see if i can use this xpath expression "//emailAddress" but it doesnt return me the tags inside inside it. maybe i am doing it wrong. i am pretty new to using xpath.

i could do something like this:

//emailAddress/value | //emailAddress/typeSource | .. but doing that will list all elements values together if im not mistaken leaving me to work out when i have finished reading from a specific emailAddress tag and going to the next emailAddress tag.

well to sum up my needs i basically want this to be returned similar to how you would return results from a bog standard sql query that returns results in a row. i.e. if your sql query produces 10 emailAddress, it will return each emailAddress in a row and i can simply iterate over "each emailAddress" and get the appropriate value based on the colunm name or index.

2
  • You will get better answers if you post your code as well as your XML. I suspect that your problem is that you need to specify the NODESET return type, but without code it's impossible to say. Commented Nov 1, 2010 at 16:24
  • Mate have a read on this topic. the question has already been answered. cheers anyway Commented Nov 3, 2010 at 15:51

4 Answers 4

3

No,

//emailAddress

doesn't return the tags inside, that is correct. What it does return is a NodeList/NodeSet. To actually get the values you can do something like this:

String emailpath = "//emailAddress";
String emailvalue = ".//value";

XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xpath = xPathFactory.newXPath();
Document document;
public XpathStuff(String file) throws ParserConfigurationException, IOException, SAXException {
    DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = docFactory.newDocumentBuilder();

    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
    document = builder.parse(bis);

    NodeList nodeList = getNodeList(document, emailpath);
    for(int i = 0; i < nodeList.getLength(); i++){
        System.out.println(getValue(nodeList.item(i), emailvalue));
    }
    bis.close();        
}

public NodeList getNodeList(Document doc, String expr) {
    try {
        XPathExpression pathExpr = xpath.compile(expr);
        return (NodeList) pathExpr.evaluate(doc, XPathConstants.NODESET);
    } catch (XPathExpressionException e) {
        e.printStackTrace();
    }
    return null;
}


//extracts the String value for the given expression
private String getValue(Node n, String expr) {
    try {
        XPathExpression pathExpr = xpath.compile(expr);
        return (String) pathExpr.evaluate(n,
                XPathConstants.STRING);
    } catch (XPathExpressionException e) {
        e.printStackTrace();
    }
    return null;
}

Maybe I should point out that when iterating over the Nodelist, in .//values the first dot means the current context. Without the dot you would get the first node all the time.

Sign up to request clarification or add additional context in comments.

1 Comment

yea i was wondering what that . means im guessing somehow it knows which current <emailAddress> to retrieve the appropriate value automatically behind the hood so to speak?
2
//emailAddress/*

will get these nodes in the document order.

It depends on how you want to iterate through the nodes. We do all our XML using XOM (http://www.xom.nu/) which is an easy reliable Java package. It's possible to write your own strategy using XOM calls.

2 Comments

maybe i can put //emailAddress[x]/* in a while loop and replace x with the counter but then again i need to know how many emailAddress tags there are
edit. na that wont work as that will just display the first childnode.
2

If you use XStream you can set it up quite easily. Like so:

@XStreamAlias( "EmailAddress" )
public class EmailAddress {

   @XStreamAlias()
   private String value;

   @XStreamAlias()
   private String typeSource;

   @XStreamAlias()
   private String typeUser;

   @XStreamAlias()
   private boolean primary;

   // ... the rest omitted for brevity
}

You then marshal & unmarshal quite simply like so:

XStream xstream = new XStream();
xstream.processAnnotations( EmailAddress.class );
xstream.toXML( /* Object value here */ emailAddress );
xstream.fromXML( /* String xml value here */ "" );

IDK if you have to use XPath or not, but if not I'd consider an out of the box solution like this.

Comments

0

I am totally aware this is not what you were asking for, but may consider using jibx. This is a tool for human-readable XML to POJO mapping. So I believe you could generate mapping for your email structure in a quick way and let the jibx do the work for you.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.