Author |
Message
|
Ben Davies |
Posted: Mon Oct 19, 2009 9:27 am Post subject: JavaCompute Node XML Parsing using While loop |
|
|
Newbie
Joined: 19 Oct 2009 Posts: 4 Location: United Kingdom
|
Hi Guys,
I have an issue in parsing XML using the Java Compute Node in Message Broker 6.1
Here is:-
Code: |
MbMessage inMessage = contact admin.getMessage();
MbElement inRoot = inMessage.getRootElement();
MbElement inputBody = inRoot.getLastChild();
MbElement item = inputBody.getFirstElementByPath("./SaleEnvelope/SaleList/Invoice/Item");
int count = 0;
while(item != null && item.getNextSibling() != null)
{
MbElement cursor = item.getFirstElementByPath("Description");
String description = cursor.getValue().toString();
cursor = cursor.getNextSibling().getNextSibling();
String price = cursor.getValue().toString();
item = item.getNextSibling();
}
|
The XML is :-
Code: |
<SaleEnvelope>
<Header>
<SaleListCount>1</SaleListCount>
</Header>
<SaleList>
<Invoice>
<Initial>K</Initial>
<Initial>A</Initial>
<Surname>Braithwaite</Surname>
<Item>
<Code>00</Code>
<Code>01</Code>
<Code>02</Code>
<Description>Twister</Description>
<Category>Games</Category>
<Price>00.30</Price>
<Quantity>01</Quantity>
</Item>
<Item>
<Code>02</Code>
<Code>03</Code>
<Code>01</Code>
<Description>The Times Newspaper</Description>
<Category>Books and Media</Category>
<Price>00.20</Price>
<Quantity>01</Quantity>
</Item>
<Balance>00.50</Balance>
<Currency>Sterling</Currency>
</Invoice>
</SaleList>
<Trailer>
<CompletionTime>12.00.00</CompletionTime>
</Trailer>
</SaleEnvelope> |
It reads in the data from the XML
node fine i.e. 'Description' and 'Price' and iterates round it twice. But for some reason it trys to do it a 3rd time, and as there are no more nodes to read, it crashes. I'm new to using this XML parser so was hoping someone might be able to shed some light on it. I have tried a number of different approaches but all seem to fail.
Any ideas much appreciated as all the documentation ive seen (Red Book and web sites) point to using this 'while' loop to traverse the tree. I have looked at Xpath, but using something like the above is preferable.
Thanks |
|
Back to top |
|
 |
mqjeff |
Posted: Mon Oct 19, 2009 9:44 am Post subject: |
|
|
Grand Master
Joined: 25 Jun 2008 Posts: 17447
|
Balance and Currency are both nextSibling()s.
Maybe you don't want to getFirstElementByPath, maybe you want to getAllElementsByPath. or whatever it is called. |
|
Back to top |
|
 |
WMBDEV1 |
Posted: Mon Oct 19, 2009 12:26 pm Post subject: |
|
|
Sentinel
Joined: 05 Mar 2009 Posts: 888 Location: UK
|
Of course you could do this in ESQL also which should perform better for simple transforms.
You can then MOVE a REFERENCE variable to its NEXTSIBLING specifying an element NAME of "Item" so that it will be moved to the next Item element only if one exists. |
|
Back to top |
|
 |
mvsivaiah |
Posted: Mon Oct 19, 2009 11:22 pm Post subject: |
|
|
 Apprentice
Joined: 30 May 2008 Posts: 25
|
I just expect you are missing " out.propagate(outAssembly); " within the while loop. Not sure, you can try it out.
you may also try for loop, something like:
for(int count=0;count<item.size();count++){
All the best. _________________ Venkat. |
|
Back to top |
|
 |
Gaya3 |
Posted: Mon Oct 19, 2009 11:46 pm Post subject: |
|
|
 Jedi
Joined: 12 Sep 2006 Posts: 2493 Location: Boston, US
|
i know this issue,
The getNextSibling() is mainly for Database record traversing, thats the reason it iterates one extra.
evaluateXPath would be the right option here.
here are some ideas :
Get the list using this way
(List<MbElement>)inputBody.evaluateXPath("./SaleEnvelope/SaleList/Invoice/Item")
then put a loop like this
Code: |
for (MbElement item: (List<MbElement>)inputBody.evaluateXPath("./SaleEnvelope/SaleList/Invoice/Item"))
{
MbElement cursor = item.getFirstElementByPath("Description");
String description = cursor.getValue().toString();
cursor = cursor.getNextSibling().getNextSibling();
String price = cursor.getValue().toString();
}
|
Note: I havent tested the above code, but this idea will work out for you, i have done the similar logic in our requirements _________________ Regards
Gayathri
-----------------------------------------------
Do Something Before you Die |
|
Back to top |
|
 |
Bartez75 |
Posted: Tue Oct 20, 2009 12:00 am Post subject: |
|
|
 Voyager
Joined: 26 Oct 2006 Posts: 80 Location: Poland, Wroclaw
|
Maybe you should check inside of the loop if the item element is "Item" like
Code: |
if (item.getName().equals("Item")){
} |
so you can try it like that (just a thought, not sure if this will work):
Code: |
MbElement item = inputBody.getFirstElementByPath("./SaleEnvelope/SaleList/Invoice/Item");
while(item != null){
if (item.getName().equals("Item")){
MbElement cursorElement = item.getFirstElementByPath("Description");
String description = cursorElement.getValue().toString();
MbElement priceElement = item.getFirstElementByPath("Price");
String price = priceElement.getValue().toString();
}
item = item.getNextSibling();
}
|
And it is not very nice |
|
Back to top |
|
 |
WMBDEV1 |
Posted: Tue Oct 20, 2009 12:45 am Post subject: |
|
|
Sentinel
Joined: 05 Mar 2009 Posts: 888 Location: UK
|
mvsivaiah wrote: |
I just expect you are missing " out.propagate(outAssembly); " within the while loop. Not sure, you can try it out.
|
What? The OP didnt state that he wanted to break the XML message into lots of smaller ones. Also, this would not achieve the behaviour the OP was expecting as you have not addressed the fact that Balance and Currency are both nextSibling()s (as stated by Jeff)
gaya3 wrote: |
i know this issue,
The getNextSibling() is mainly for Database record traversing, thats the reason it iterates one extra.
|
Is it? I thought it was for tree traversal and i've never encountered a DB retrival request that retruns an extra iteration for fun.
Also to what issue are you refering to? Are you saying theres a bug with getNextSibling()? Do you think Jeffs explanation is not the root cause of this behaviour? |
|
Back to top |
|
 |
Gaya3 |
Posted: Tue Oct 20, 2009 1:15 am Post subject: |
|
|
 Jedi
Joined: 12 Sep 2006 Posts: 2493 Location: Boston, US
|
i experienced it when i was trying to do a loop in XML.
directly i went and used Xpath for this, if you change the code, what i suggested it will work. _________________ Regards
Gayathri
-----------------------------------------------
Do Something Before you Die |
|
Back to top |
|
 |
Ben Davies |
Posted: Tue Oct 20, 2009 3:59 am Post subject: |
|
|
Newbie
Joined: 19 Oct 2009 Posts: 4 Location: United Kingdom
|
Thnaks very much Gaya3. Works as intended
Code: |
for (MbElement item: (List<MbElement>)inputBody.evaluateXPath("./SaleEnvelope/SaleList/Invoice/Item"))
{
MbElement cursor = item.getFirstElementByPath("Description");
String description = cursor.getValue().toString();
cursor = cursor.getNextSibling().getNextSibling(); // Price element
String price = cursor.getValue().toString();
MbElement outCostEnvelope = outSaleEnvelope.createElementAsFirstChild(MbXMLNSC.FOLDER, "Cost", null);
outCostEnvelope.createElementAsLastChild(MbXMLNSC.FIELD, "Description" , description);
outCostEnvelope.createElementAsLastChild(MbXMLNSC.FIELD, "Price" , price);
}
|
 |
|
Back to top |
|
 |
|