Forum Discussion

Said's avatar
Said
Contributor
6 years ago

How to select nodes matching criteria

Hi all,

Because large number of <c> elements in the response my checks take very long (hours). See simplified respresentation of response below. The actual response has much more elements.

<a>
	<b>
		<c>
			<d>1</d>
			<e>2</e>
			<f>3</f>
		</c>
		<c>
			<d>4</d>
			<e>5</e>
			<f>6</f>
		</c>
		<c>
			<d>7</d>
			<f>8</f>
		</c>
		<c>
			<d>9</d>
			<e>10</e>
			<f>11</f>
		</c>
		<c>
			<d>12</d>
			<f>13</f>
		</c>
		<c>
			<d>15</d>
			<e>16</e>
			<f>17</f>
		</c>
	</b>
</a>

See example of my code to process response below:

int totC = respHolder.getNodeValue("count(//b/c)").toInteger();
for (int i=1; i<=totC; i++) {
	if (respHolder.getNodeValue("exists(//b/c[$i]/e)") == "false") continue;
	// rest of my code
}

I have calcutated that only 40% of the <c> elements have an <e> element. So I am looking for a way to only get <c> elements that have an <e> element.  Then loop through them. How can I do this?

 

Thanks in advance.

  • Said: That's what I was afraid of. Unfortunately if you have to calculate each and every value that exists in the /b/c node where E exists, then you have to process every node individually and that is going to take time. I ran into similar problems because, as you stated, the arrays that the statements I provided would be completely and totally out of order and out of sync. 

     

    In my experience, there's no good way to do this other than parsing every //b/c node. 

  • groovyguy's avatar
    groovyguy
    Community Hero

     

    Unfortunately, as far as I am aware, this is highly dependent on what you are doing and checking if this snippet returns true. 

    exists(//b/c[$i]/e)

     

    Can you give us an example of what you are doing in that scenario? If you need to check the value of D or F if E exists, you can play with an XPATH statement like below. This says, for the entire response, get me the value of //b/c/d where //b/c/e exists. It returns it as an array. 

     

    log.info(holder["//b/c[exists(./e)]/d/text()"].toString());

    This outputs [1, 4, 9, 15] based on the sample response you gave. 

    • Said's avatar
      Said
      Contributor

      groovyguy, thanks alot for you fast response :smileyhappy:

      To answer you question: Can you give us an example of what you are doing in that scenario?

      I need to copy the values of d, e, f (and more, I left them out to keep it to the point) to an in memory database, to that I can use them to verify a calculation.

      Below statement gives me an array of all d when e exists.

      String[] d = respHolder["//b/c[exists(./e)]/d/text()"];

       I could use same type of statement to create and array for e and f. But what if e.g. f is not there in one of the nodes. The arrays are then not in sync. How could I deal with this?

      • groovyguy's avatar
        groovyguy
        Community Hero

        Said: That's what I was afraid of. Unfortunately if you have to calculate each and every value that exists in the /b/c node where E exists, then you have to process every node individually and that is going to take time. I ran into similar problems because, as you stated, the arrays that the statements I provided would be completely and totally out of order and out of sync. 

         

        In my experience, there's no good way to do this other than parsing every //b/c node.