xpathgroovy

Xpath to get all Child Nodes as XML in Groovy


I am receiving below XML as request

<orderMessageRequest>
    <wave>wave01</wave>
    <orderLine>
        <orderLineNumber>1</orderLineNumber>
        <dn>123</dn>
        <productId>TestProduct1</productId>
        <attributeValue>
            <name>lotCode</name>
            <value>123</value>
            <name>lotCode1</name>
            <value>1234</value>
        </attributeValue>
    </orderLine>
    <orderLine>
        <orderLineNumber>2</orderLineNumber>
        <dn>4032455365</dn>
        <productId>TestProduct2</productId>
    </orderLine>
</orderMessageRequest>

I am using groovy and XPath to get orderLine as

//orderMessageRequest/orderLine[1] or //orderMessageRequest/orderLine[1]/node()

There are 2 problem i am facing in my code.

  1. Even though i am using [0] or [1] in orderLine path, its returning only first orderLine
  2. Its just returning value not complete node

my code

String processXml( String xml, String xpathQuery ) {
  def xpath = XPathFactory.newInstance().newXPath()
  def builder     = DocumentBuilderFactory.newInstance().newDocumentBuilder()
  def inputStream = new ByteArrayInputStream( xml.bytes )
  def records     = builder.parse(inputStream).documentElement
  def x=xpath.evaluate( xpathQuery, records );
return x;

def x=processXml( testxml, '//orderTuPickConfirmationMessageRequest/orderLine[1]/node()' )

What is wrong here, i am expecting result as based on orderLine[0/1] it should return complete orderLine for eg orderLine[0]

<orderLine>
        <orderLineNumber>1</orderLineNumber>
        <dn>123</dn>
        <productId>TestProduct1</productId>
        <attributeValue>
            <name>lotCode</name>
            <value>123</value>
            <name>lotCode1</name>
            <value>1234</value>
        </attributeValue>
    </orderLine>

Solution

  • Using XPath that way is just use Java's APIs in Groovy. But Groovy offers a much simpler interface for working with XML with XmlSlurper. For example, I was able to get this script working with your excerpt:

    import groovy.xml.*
    
    String xmlText = """
    <orderMessageRequest>
        <wave>wave01</wave>
        <orderLine>
            <orderLineNumber>1</orderLineNumber>
            <dn>123</dn>
            <productId>TestProduct1</productId>
            <attributeValue>
                <name>lotCode</name>
                <value>123</value>
                <name>lotCode1</name>
                <value>1234</value>
            </attributeValue>
        </orderLine>
        <orderLine>
            <orderLineNumber>2</orderLineNumber>
            <dn>4032455365</dn>
            <productId>TestProduct2</productId>
        </orderLine>
    </orderMessageRequest>
    """
    
    XmlSlurper slurper = new XmlSlurper()
    def xml = slurper.parseText( xmlText )
    
    println("-----Print First Node-----")
    println( XmlUtil.serialize(xml.orderLine[0]) )
    println("-----Print Second Node-----")
    println( XmlUtil.serialize(xml.orderLine[1]) )
    
    println("-----Print All Nodes-----")
    xml.orderLine.each { orderLine -> println( XmlUtil.serialize( orderLine ) ) }
    
    println("Done.")
    

    Using XmlSlurper is very similar to XPath, but just easier API-wise.

    I also tried out your code, and I got a org.xml.sax.SAXParseException; lineNumber: 2; columnNumber: 9; Premature end of file. I never figured out why it wasn't working everything looked in order. There is a typo in the xpath:

    //orderTuPickConfirmationMessageRequest/orderLine[1]/node() 
    

    probably you meant //orderToPick....

    //orderToPickConfirmationMessageRequest/orderLine[1]/node()
    

    But even after fixing that it still didn't like it. XmlSlurper was able to parse it without issue though so ¯\_(ツ)_/¯