Search code examples
javaxpathdom4j

Trying to use xPath on an xml document created in memory not from a file


I am exporting data into an xml file. I am looping through a database exporting various data and need to check the xml document to see if it exists already as I'm exporting data.

When I try using xPath to query the xml document it returns null. Do I have to save the xml file then reload it for xPath to work? Am I doing something wrong? Here is my test code below. Note, I tried using xmlDoc.selectNodes as well as xPath. Still no love

Here is the console output

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

<root>
  <authors>
    <author>
      <name>Steven Rieger</name>
      <location>Illinois</location>
    </author>
    <author>
      <name>Dylan Rieger</name>
      <location>Illinois</location>
    </author>
  </authors>
</root>
org.dom4j.tree.DefaultDocument@e26948 [Document: name null]


public class TestXML
{

    public static void writeXmlDoc( Document document ) throws IOException
    {

        OutputFormat format = OutputFormat.createPrettyPrint();
        // lets write to a file
        XMLWriter writer = new XMLWriter( new FileWriter( "c:\\temp\\output.xml" ), format );
        writer.write( document );
        writer.close();

        // Pretty print the document to System.out
        writer = new XMLWriter( System.out, format );
        writer.write( document );
    }

    public static void main( String[] args ) throws Exception
    {
        org.dom4j.Document xmlDoc;
        List<Node> authors = null;
        Element author = null;
        try
        {
            xmlDoc = DocumentHelper.createDocument();
            Element root = xmlDoc.addElement( "root" );
            Element authorsElement = root.addElement( "authors" );
            Element author1 = authorsElement.addElement( "author" );
            author1.addElement( "name" ).addText( "Steven Rieger" );
            author1.addElement( "location" ).addText( "Illinois" );

            Element author2 = authorsElement.addElement( "author" );
            author2.addElement( "name" ).addText( "Dylan Rieger" );
            author2.addElement( "location" ).addText( "Illinois" );



            writeXmlDoc( xmlDoc );

//          authors = xmlDoc.selectNodes( "/authors" );

             XPath xpathSelector = DocumentHelper.createXPath("/authors");
             authors = xpathSelector.selectNodes( xmlDoc );

            for (Iterator<Node> authorIterator = authors.iterator(); authorIterator.hasNext();)
            {
                author = (Element) authorIterator.next();
                System.out.println( "Author: " + author.attributeValue( "name" ) );
                System.out.println( "  Location: " + author.attributeValue( "location" ) );
                System.out.println( "  FullName: " + author.getText() );
            }

            System.out.println( xmlDoc.toString() );
        } catch ( Exception e )
        {
            e.printStackTrace();
        }
    }
}

Solution

  • Your query retunrs null because authors is not the root of the xml. You may use this xpath instead:

    XPath xpathSelector = DocumentHelper.createXPath("/root/authors/author");
    

    The other problem is that you first store the name and state as child elements of the author, but later you try to read them as attributes. See https://www.w3schools.com/xml/xml_dtd_el_vs_attr.asp You may try to read them in the loop like this:

    System.out.println("Author: " + author.selectSingleNode("name").getText());
    System.out.println("  Location: " + author.selectSingleNode("location").getText());