Menu

Need some helps with <jt:forEach>

Hung Cu
2017-02-10
2017-02-10
  • Hung Cu

    Hung Cu - 2017-02-10

    I am working on a project where I need to use the forEach tag to pull the information from the xml node(s). I keep run into a problem with "Expected a "java.util.Collection" for "items", got a "java.util.LinkedHashMap". Are there any ways that I can override the behavior of the <foreach> tag so that it always create a collection(put a item into the collection if the item is not a type of Collection) ?</foreach>

     
  • Etienne Canaud

    Etienne Canaud - 2017-02-11

    Hi Hung Cu,

    Could you share more info about the XML you're parsing and how you want to use forEach to iterate over its contents? If you got a Map, you'll need to give JETT more info on what to iterate over.

    It would not make sense to create a collection with one item from a HashMap and iterate over just it, because you wouln't iterate anything ; just use direct accessor to access the Map object if you know that a Map is returned, not a forEach.

    Also, if your point is that you would like to use forEach to go over the XML elements, then you cannot iterate a Map like you could iterate a Collection, because you wouldn't know what to iterate on. The keys? The values? The entries? If you have some XML it may be very clear for you what you want to iterate over, but if we just consider the Map structure, it's not a call that JETT can do for you.

    That being said, if there's one reproach I have for the JETT forEach tag, it's that it will only iterate a Collection and not an array[]. Having to call Arrays.asList() ourselves adds unnecessary complexity, but it's far from being a major pain :)

    Cheers,
    Etienne.

     
  • Hung Cu

    Hung Cu - 2017-02-12

    Thanks, I figured out the solution. It works but I don't know if this is a good way or not.
    <jt:foreach items="${if(root.get('children').getClass().getName() == 'java.util.ArrayList'){return root.children}else{var t = new(java.util.ArrayList,1); t.add(root.children); return t;}}" var="children"> {children.label}</jt:foreach>

     

    Last edit: Hung Cu 2017-02-12
  • Etienne Canaud

    Etienne Canaud - 2017-02-12

    OK, now I understand what your problem is.

    Your XML parser will return a List if root has many children, or a single object if there's one child.

    Shouldn't the type depend on your XML Schema? If you don't have a schema then your XML parser is doing its best and your code is the best way I can think to handle this case.
    However, if you know your XML schema, you should bind this to a java class where the "children" element in root object is a List, so you wouldn't have a problem. It would be a List whether there's one or more child.

     
  • Hung Cu

    Hung Cu - 2017-02-13

    Thank,
    I thought about doing that way too but I realized that it is not a good solution in our case because it would break our ${xml.child.label} syntax. We don't want to go back to every excel templates and swich ${xml.child.label} to <jt:foreach>. Therefore, I hope that there were a way that I could override the default behavior of the <jt:foreach> instead of writting a long JEXL syntax.</jt:foreach></jt:foreach>

     

Log in to post a comment.

MongoDB Logo MongoDB