Forum Discussion

pkunst's avatar
pkunst
Contributor
11 years ago

[Resolved] Counting nodes of response

Hi together
I have another problem with SaopUI.
I have such a structure as response
<Envelope>
<Header>
</Header>
<Body>
<Response>
<Result>
<List>
<ElementOfList>
</ElementOfList>
<ElementOfList>
</ElementOfList>
<ElementOfList>
</ElementOfList>
<ElementOfList>
</ElementOfList>
</List>
<Result>
</Response>
</Body>
</Envelope>

I am trying to count the nodes of a response. May first idea was to put the node in a string and then count the substring “ElementOfList” and divide it with 2. It works nearly fine except that the .count method count not enough. I had 32 child nodes of “List” but it only counts 31.
String list =  testRunner.testCase.getPropertyValue( "purchaseOrderItemDTOList")
int i= list.count("PurchaseOrderItemDTO")
testRunner.testCase.setPropertyValue( "counter",i.toString())



So I search on your homepage and found that: http://www.soapui.org/Scripting-Properties/tips-a-tricks.html#3-2-count-nodes
That does not work at all. The result is 0 and I don’t know why. Hope you can help me.
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def holder = groovyUtils.getXmlHolder("GetListOfPurchaseOrderItems#Response")
log.info holder
def i = holder["count(//Envelope/Body/Response/Result//List/ChildElement)"]


Regards
Patrick

6 Replies

  • nmrao's avatar
    nmrao
    Champion Level 3
    Ok. Not sure if '//' in below xpath of yours causing any problem.

    May you simply try the below:
    Replace below line
    def i = holder["count(//Envelope/Body/Response/Result//List/ChildElement)"]

    with

    def i = holder["count(//*:ElementOfList)"] //if there is namespaces involved
    /*def i = holder["count(//ElementOfList)"] //if no namespace */
    log.info "ElementOfList - node count ${i}"
  • PaulDonny's avatar
    PaulDonny
    Regular Contributor
    Here is a sample script that does what you want, it's in Groovy so it would require a groovy step. I am certain that there is better ways to do this but I used regexp in order to make it more versatile for other uses.

    First example, used for matching counting all child elements:

    def testRan = context.testCase.getTestStepByName("Test Request");
    def xml = testRan.getPropertyValue("Response");
    def regexp = ("(?m)<([^<>]+)>(.*?)</\\1>");
    def matcher = xml =~ regexp;
    int count = 0;
    matcher.each {
    count++;
    }
    log.info count;



    Example 2 is the same, except change the regexp line to:

    def regexp = ("(?m)<(ElementOfList)>(.*?)</\\1>");


    Where ElementOfList is the value you want. After your done counting, do whatever you want. The logic for the count and code is in the matcher.each section so if you want to manipulate the data just do it[2] for the value of the node and it[1] for the node's name.
  • nmrao's avatar
    nmrao
    Champion Level 3
    @Patrick,

    I can see count in action to get the node count using the details you mentioned. Not sure if there is any issue with the namespaces or something wrong in the xpath.

    It does not have ChildElement in the xml fragment you mentioned where that was referred in xpath.
  • nmrao wrote:
    @Patrick,

    I can see count in action to get the node count using the details you mentioned. Not sure if there is any issue with the namespaces or something wrong in the xpath.

    It does not have ChildElement in the xml fragment you mentioned where that was referred in xpath.


    Sry, it was my fault, while I wrote the post.
    I mean not ChildElement but ElementOfList

    PaulM
    I will try you version of counting the string and will post if it worked.
  • nmrao wrote:
    Ok. Not sure if '//' in below xpath of yours causing any problem.

    May you simply try the below:
    Replace below line
    def i = holder["count(//Envelope/Body/Response/Result//List/ChildElement)"]

    with

    def i = holder["count(//*:ElementOfList)"] //if there is namespaces involved
    /*def i = holder["count(//ElementOfList)"] //if no namespace */
    log.info "ElementOfList - node count ${i}"


    Thank you.

    def i = holder["count(//*:ElementOfList)"] //if there is namespaces involved


    works fine.