Implement a custom JUEL resolver for performing XPath queries on DOM Nodes
-------------------------------------------------------------------------- Key: OFBIZ-2397 URL: https://issues.apache.org/jira/browse/OFBIZ-2397 Project: OFBiz Issue Type: New Feature Components: framework Affects Versions: SVN trunk Reporter: Scott Gray Assignee: Scott Gray Attachments: XPath.patch In order to make XML easy to read using simple methods I've implemented a custom JUEL ELResolver that handles string properties for objects implementing org.w3c.dom.Node and org.apache.xerces.dom.NodeImpl. It takes the String and compiles it into an XPathExpression which is then evaluated against the base Node. The JUEL evaluation returns either null, a single Node or a NodeList depending on the result of the XPath evaluation. Type conversion is handled using the set operation like so: {code} // Get the key attribute node from the first property element, note no type is specified so no conversion takes place <set field="attributeNode" from-field="document['resource/property[1]/@key']"/> // ObjectType.simpleTypeConvert calls getTextContent on the node, if the target type is anything other than a string it calls simpleTypeConvert again using the string // Get the value of the attribute key from the first property element <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="String"/> // If the key value were an Integer you could do this, the conversion would be node.getTextContent -> String -> Integer <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="Integer"/> {code} I've also added support for NodeList to the iterate tag so that you can do this: {code:xml} <iterate entry="node" list="parameters.document['resource/property']"> <log level="always" message="Property Key: ${node['@key']}"/> <log level="always" message="First Value: ${node['value[1]']}"/> </iterate> {code} -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online. |
[ https://issues.apache.org/jira/browse/OFBIZ-2397?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Scott Gray updated OFBIZ-2397: ------------------------------ Attachment: XPath.patch > Implement a custom JUEL resolver for performing XPath queries on DOM Nodes > -------------------------------------------------------------------------- > > Key: OFBIZ-2397 > URL: https://issues.apache.org/jira/browse/OFBIZ-2397 > Project: OFBiz > Issue Type: New Feature > Components: framework > Affects Versions: SVN trunk > Reporter: Scott Gray > Assignee: Scott Gray > Attachments: XPath.patch > > > In order to make XML easy to read using simple methods I've implemented a custom JUEL ELResolver that handles string properties for objects implementing org.w3c.dom.Node and org.apache.xerces.dom.NodeImpl. It takes the String and compiles it into an XPathExpression which is then evaluated against the base Node. The JUEL evaluation returns either null, a single Node or a NodeList depending on the result of the XPath evaluation. > Type conversion is handled using the set operation like so: > {code} > // Get the key attribute node from the first property element, note no type is specified so no conversion takes place > <set field="attributeNode" from-field="document['resource/property[1]/@key']"/> > // ObjectType.simpleTypeConvert calls getTextContent on the node, if the target type is anything other than a string it calls simpleTypeConvert again using the string > // Get the value of the attribute key from the first property element > <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="String"/> > // If the key value were an Integer you could do this, the conversion would be node.getTextContent -> String -> Integer > <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="Integer"/> > {code} > I've also added support for NodeList to the iterate tag so that you can do this: > {code:xml} > <iterate entry="node" list="parameters.document['resource/property']"> > <log level="always" message="Property Key: ${node['@key']}"/> > <log level="always" message="First Value: ${node['value[1]']}"/> > </iterate> > {code} -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online. |
In reply to this post by Nicolas Malin (Jira)
[ https://issues.apache.org/jira/browse/OFBIZ-2397?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12704835#action_12704835 ] Adrian Crum commented on OFBIZ-2397: ------------------------------------ Scott, This is a great idea, but I think it would be simpler to use a UEL function instead of an ELResolver. The you could use something like: {code} <set field="attributeNode" from-field="util:getNode('resource/property[1]/@key')"/> {code} > Implement a custom JUEL resolver for performing XPath queries on DOM Nodes > -------------------------------------------------------------------------- > > Key: OFBIZ-2397 > URL: https://issues.apache.org/jira/browse/OFBIZ-2397 > Project: OFBiz > Issue Type: New Feature > Components: framework > Affects Versions: SVN trunk > Reporter: Scott Gray > Assignee: Scott Gray > Attachments: XPath.patch > > > In order to make XML easy to read using simple methods I've implemented a custom JUEL ELResolver that handles string properties for objects implementing org.w3c.dom.Node and org.apache.xerces.dom.NodeImpl. It takes the String and compiles it into an XPathExpression which is then evaluated against the base Node. The JUEL evaluation returns either null, a single Node or a NodeList depending on the result of the XPath evaluation. > Type conversion is handled using the set operation like so: > {code} > // Get the key attribute node from the first property element, note no type is specified so no conversion takes place > <set field="attributeNode" from-field="document['resource/property[1]/@key']"/> > // ObjectType.simpleTypeConvert calls getTextContent on the node, if the target type is anything other than a string it calls simpleTypeConvert again using the string > // Get the value of the attribute key from the first property element > <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="String"/> > // If the key value were an Integer you could do this, the conversion would be node.getTextContent -> String -> Integer > <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="Integer"/> > {code} > I've also added support for NodeList to the iterate tag so that you can do this: > {code:xml} > <iterate entry="node" list="parameters.document['resource/property']"> > <log level="always" message="Property Key: ${node['@key']}"/> > <log level="always" message="First Value: ${node['value[1]']}"/> > </iterate> > {code} -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online. |
In reply to this post by Nicolas Malin (Jira)
[ https://issues.apache.org/jira/browse/OFBIZ-2397?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12704839#action_12704839 ] Adrian Crum commented on OFBIZ-2397: ------------------------------------ Thinking about it more, you could also create a getDocument UEL function, then prefix both functions with xml. {code} <set field="document" from-field="xml:getDocument('component://...')"/> <set field="attributeNode" from-field="xml:getNode(document, 'resource/property[1]/@key')"/> {code} > Implement a custom JUEL resolver for performing XPath queries on DOM Nodes > -------------------------------------------------------------------------- > > Key: OFBIZ-2397 > URL: https://issues.apache.org/jira/browse/OFBIZ-2397 > Project: OFBiz > Issue Type: New Feature > Components: framework > Affects Versions: SVN trunk > Reporter: Scott Gray > Assignee: Scott Gray > Attachments: XPath.patch > > > In order to make XML easy to read using simple methods I've implemented a custom JUEL ELResolver that handles string properties for objects implementing org.w3c.dom.Node and org.apache.xerces.dom.NodeImpl. It takes the String and compiles it into an XPathExpression which is then evaluated against the base Node. The JUEL evaluation returns either null, a single Node or a NodeList depending on the result of the XPath evaluation. > Type conversion is handled using the set operation like so: > {code} > // Get the key attribute node from the first property element, note no type is specified so no conversion takes place > <set field="attributeNode" from-field="document['resource/property[1]/@key']"/> > // ObjectType.simpleTypeConvert calls getTextContent on the node, if the target type is anything other than a string it calls simpleTypeConvert again using the string > // Get the value of the attribute key from the first property element > <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="String"/> > // If the key value were an Integer you could do this, the conversion would be node.getTextContent -> String -> Integer > <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="Integer"/> > {code} > I've also added support for NodeList to the iterate tag so that you can do this: > {code:xml} > <iterate entry="node" list="parameters.document['resource/property']"> > <log level="always" message="Property Key: ${node['@key']}"/> > <log level="always" message="First Value: ${node['value[1]']}"/> > </iterate> > {code} -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online. |
In reply to this post by Nicolas Malin (Jira)
[ https://issues.apache.org/jira/browse/OFBIZ-2397?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12704841#action_12704841 ] Scott Gray commented on OFBIZ-2397: ----------------------------------- Hi Adrian I like the getDocument function but the getNode would just result in more typing. I used the custom resolver because it seemed to fit into the pattern of other JUEL resolvers for retrieving properties from an object, XPath just happens to be a very powerful way of doing that for nodes. And what do you mean by simpler, that it would have been simpler if I hadn't already written the code? :-) > Implement a custom JUEL resolver for performing XPath queries on DOM Nodes > -------------------------------------------------------------------------- > > Key: OFBIZ-2397 > URL: https://issues.apache.org/jira/browse/OFBIZ-2397 > Project: OFBiz > Issue Type: New Feature > Components: framework > Affects Versions: SVN trunk > Reporter: Scott Gray > Assignee: Scott Gray > Attachments: XPath.patch > > > In order to make XML easy to read using simple methods I've implemented a custom JUEL ELResolver that handles string properties for objects implementing org.w3c.dom.Node and org.apache.xerces.dom.NodeImpl. It takes the String and compiles it into an XPathExpression which is then evaluated against the base Node. The JUEL evaluation returns either null, a single Node or a NodeList depending on the result of the XPath evaluation. > Type conversion is handled using the set operation like so: > {code} > // Get the key attribute node from the first property element, note no type is specified so no conversion takes place > <set field="attributeNode" from-field="document['resource/property[1]/@key']"/> > // ObjectType.simpleTypeConvert calls getTextContent on the node, if the target type is anything other than a string it calls simpleTypeConvert again using the string > // Get the value of the attribute key from the first property element > <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="String"/> > // If the key value were an Integer you could do this, the conversion would be node.getTextContent -> String -> Integer > <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="Integer"/> > {code} > I've also added support for NodeList to the iterate tag so that you can do this: > {code:xml} > <iterate entry="node" list="parameters.document['resource/property']"> > <log level="always" message="Property Key: ${node['@key']}"/> > <log level="always" message="First Value: ${node['value[1]']}"/> > </iterate> > {code} -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online. |
In reply to this post by Nicolas Malin (Jira)
[ https://issues.apache.org/jira/browse/OFBIZ-2397?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12704848#action_12704848 ] Adrian Crum commented on OFBIZ-2397: ------------------------------------ I meant the code would be simpler. UEL functions are very easy to create. You're right, the ELResolver approach does make for prettier syntax. > Implement a custom JUEL resolver for performing XPath queries on DOM Nodes > -------------------------------------------------------------------------- > > Key: OFBIZ-2397 > URL: https://issues.apache.org/jira/browse/OFBIZ-2397 > Project: OFBiz > Issue Type: New Feature > Components: framework > Affects Versions: SVN trunk > Reporter: Scott Gray > Assignee: Scott Gray > Attachments: XPath.patch > > > In order to make XML easy to read using simple methods I've implemented a custom JUEL ELResolver that handles string properties for objects implementing org.w3c.dom.Node and org.apache.xerces.dom.NodeImpl. It takes the String and compiles it into an XPathExpression which is then evaluated against the base Node. The JUEL evaluation returns either null, a single Node or a NodeList depending on the result of the XPath evaluation. > Type conversion is handled using the set operation like so: > {code} > // Get the key attribute node from the first property element, note no type is specified so no conversion takes place > <set field="attributeNode" from-field="document['resource/property[1]/@key']"/> > // ObjectType.simpleTypeConvert calls getTextContent on the node, if the target type is anything other than a string it calls simpleTypeConvert again using the string > // Get the value of the attribute key from the first property element > <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="String"/> > // If the key value were an Integer you could do this, the conversion would be node.getTextContent -> String -> Integer > <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="Integer"/> > {code} > I've also added support for NodeList to the iterate tag so that you can do this: > {code:xml} > <iterate entry="node" list="parameters.document['resource/property']"> > <log level="always" message="Property Key: ${node['@key']}"/> > <log level="always" message="First Value: ${node['value[1]']}"/> > </iterate> > {code} -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online. |
In reply to this post by Nicolas Malin (Jira)
[ https://issues.apache.org/jira/browse/OFBIZ-2397?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12704851#action_12704851 ] Scott Gray commented on OFBIZ-2397: ----------------------------------- I was pleasantly surprised by how easy it was to write a new resolver it must have taken about an hour or two to get from never having looked at how JUEL works before to having a working POC. Anyway if you're happy with the implementation let me know and I'll go ahead and commit it. The main reason I posted it to jira was so that you could take a look before it went in since you're our resident JUEL expert :-) > Implement a custom JUEL resolver for performing XPath queries on DOM Nodes > -------------------------------------------------------------------------- > > Key: OFBIZ-2397 > URL: https://issues.apache.org/jira/browse/OFBIZ-2397 > Project: OFBiz > Issue Type: New Feature > Components: framework > Affects Versions: SVN trunk > Reporter: Scott Gray > Assignee: Scott Gray > Attachments: XPath.patch > > > In order to make XML easy to read using simple methods I've implemented a custom JUEL ELResolver that handles string properties for objects implementing org.w3c.dom.Node and org.apache.xerces.dom.NodeImpl. It takes the String and compiles it into an XPathExpression which is then evaluated against the base Node. The JUEL evaluation returns either null, a single Node or a NodeList depending on the result of the XPath evaluation. > Type conversion is handled using the set operation like so: > {code} > // Get the key attribute node from the first property element, note no type is specified so no conversion takes place > <set field="attributeNode" from-field="document['resource/property[1]/@key']"/> > // ObjectType.simpleTypeConvert calls getTextContent on the node, if the target type is anything other than a string it calls simpleTypeConvert again using the string > // Get the value of the attribute key from the first property element > <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="String"/> > // If the key value were an Integer you could do this, the conversion would be node.getTextContent -> String -> Integer > <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="Integer"/> > {code} > I've also added support for NodeList to the iterate tag so that you can do this: > {code:xml} > <iterate entry="node" list="parameters.document['resource/property']"> > <log level="always" message="Property Key: ${node['@key']}"/> > <log level="always" message="First Value: ${node['value[1]']}"/> > </iterate> > {code} -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online. |
In reply to this post by Nicolas Malin (Jira)
[ https://issues.apache.org/jira/browse/OFBIZ-2397?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12705002#action_12705002 ] Adrian Crum commented on OFBIZ-2397: ------------------------------------ I guess we both learned something from this - I didn't know about XPath. I did notice one thing though. In your first code block you have {code} <set field="attributeNode" from-field="document['resource/property[1]/@key']"/> {code} returning a single Node. Then in the second code block you have {code} <iterate entry="node" list="parameters.document['resource/property']"> {code} returning a List of Nodes. I understand it's the XPath expression that makes the difference between a single Node or a List. I'm wondering if that will cause confusion for others. It's not a big deal - just an observation. Anyways, it would be nice if we could continue to follow the UEL syntax to select a Node from a List of Nodes: {code} <set field="nodeList" from-field="document['resource/property']"/> <set field="firstNode" from-field="nodeList[0]"/> {code} but don't let that additional enhancement prevent you from committing what you have so far. It looks great to me - go for it! > Implement a custom JUEL resolver for performing XPath queries on DOM Nodes > -------------------------------------------------------------------------- > > Key: OFBIZ-2397 > URL: https://issues.apache.org/jira/browse/OFBIZ-2397 > Project: OFBiz > Issue Type: New Feature > Components: framework > Affects Versions: SVN trunk > Reporter: Scott Gray > Assignee: Scott Gray > Attachments: XPath.patch > > > In order to make XML easy to read using simple methods I've implemented a custom JUEL ELResolver that handles string properties for objects implementing org.w3c.dom.Node and org.apache.xerces.dom.NodeImpl. It takes the String and compiles it into an XPathExpression which is then evaluated against the base Node. The JUEL evaluation returns either null, a single Node or a NodeList depending on the result of the XPath evaluation. > Type conversion is handled using the set operation like so: > {code} > // Get the key attribute node from the first property element, note no type is specified so no conversion takes place > <set field="attributeNode" from-field="document['resource/property[1]/@key']"/> > // ObjectType.simpleTypeConvert calls getTextContent on the node, if the target type is anything other than a string it calls simpleTypeConvert again using the string > // Get the value of the attribute key from the first property element > <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="String"/> > // If the key value were an Integer you could do this, the conversion would be node.getTextContent -> String -> Integer > <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="Integer"/> > {code} > I've also added support for NodeList to the iterate tag so that you can do this: > {code:xml} > <iterate entry="node" list="parameters.document['resource/property']"> > <log level="always" message="Property Key: ${node['@key']}"/> > <log level="always" message="First Value: ${node['value[1]']}"/> > </iterate> > {code} -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online. |
In reply to this post by Nicolas Malin (Jira)
[ https://issues.apache.org/jira/browse/OFBIZ-2397?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12705006#action_12705006 ] Adrian Crum commented on OFBIZ-2397: ------------------------------------ On a side note - the ELResolver class is a part of the javax.el package. It's an API. JUEL is an implementation of the javax.el API. I'm not being picky, I'm just clarifying that for anyone who might be "listening in." > Implement a custom JUEL resolver for performing XPath queries on DOM Nodes > -------------------------------------------------------------------------- > > Key: OFBIZ-2397 > URL: https://issues.apache.org/jira/browse/OFBIZ-2397 > Project: OFBiz > Issue Type: New Feature > Components: framework > Affects Versions: SVN trunk > Reporter: Scott Gray > Assignee: Scott Gray > Attachments: XPath.patch > > > In order to make XML easy to read using simple methods I've implemented a custom JUEL ELResolver that handles string properties for objects implementing org.w3c.dom.Node and org.apache.xerces.dom.NodeImpl. It takes the String and compiles it into an XPathExpression which is then evaluated against the base Node. The JUEL evaluation returns either null, a single Node or a NodeList depending on the result of the XPath evaluation. > Type conversion is handled using the set operation like so: > {code} > // Get the key attribute node from the first property element, note no type is specified so no conversion takes place > <set field="attributeNode" from-field="document['resource/property[1]/@key']"/> > // ObjectType.simpleTypeConvert calls getTextContent on the node, if the target type is anything other than a string it calls simpleTypeConvert again using the string > // Get the value of the attribute key from the first property element > <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="String"/> > // If the key value were an Integer you could do this, the conversion would be node.getTextContent -> String -> Integer > <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="Integer"/> > {code} > I've also added support for NodeList to the iterate tag so that you can do this: > {code:xml} > <iterate entry="node" list="parameters.document['resource/property']"> > <log level="always" message="Property Key: ${node['@key']}"/> > <log level="always" message="First Value: ${node['value[1]']}"/> > </iterate> > {code} -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online. |
In reply to this post by Nicolas Malin (Jira)
[ https://issues.apache.org/jira/browse/OFBIZ-2397?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Scott Gray closed OFBIZ-2397. ----------------------------- Resolution: Fixed Fix Version/s: SVN trunk Anyone using the XPath will have to know the grammar of the xml their working with and should know whether a particular expression will return a single node or a list of nodes. They would need to know that regardless of what language they are using to execute the expressions so it's not a problem unique to this situation. Besides there are a ton of online XPath expression test beds where you can paste your xml and try out different queries on it. I liked your idea about indexing into a NodeList but the problem is that NodeList is it own interface and doesn't implement Node or NodeImpl which means I would need to write another resolver or try and shoehorn it into this one. I didn't feel like doing either of those things right now, but still it would be nice at some point. Anyways thanks for the feedback/review, committed in r770915 > Implement a custom JUEL resolver for performing XPath queries on DOM Nodes > -------------------------------------------------------------------------- > > Key: OFBIZ-2397 > URL: https://issues.apache.org/jira/browse/OFBIZ-2397 > Project: OFBiz > Issue Type: New Feature > Components: framework > Affects Versions: SVN trunk > Reporter: Scott Gray > Assignee: Scott Gray > Fix For: SVN trunk > > Attachments: XPath.patch > > > In order to make XML easy to read using simple methods I've implemented a custom JUEL ELResolver that handles string properties for objects implementing org.w3c.dom.Node and org.apache.xerces.dom.NodeImpl. It takes the String and compiles it into an XPathExpression which is then evaluated against the base Node. The JUEL evaluation returns either null, a single Node or a NodeList depending on the result of the XPath evaluation. > Type conversion is handled using the set operation like so: > {code} > // Get the key attribute node from the first property element, note no type is specified so no conversion takes place > <set field="attributeNode" from-field="document['resource/property[1]/@key']"/> > // ObjectType.simpleTypeConvert calls getTextContent on the node, if the target type is anything other than a string it calls simpleTypeConvert again using the string > // Get the value of the attribute key from the first property element > <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="String"/> > // If the key value were an Integer you could do this, the conversion would be node.getTextContent -> String -> Integer > <set field="attributeValue" from-field="document['resource/property[1]/@key']" type="Integer"/> > {code} > I've also added support for NodeList to the iterate tag so that you can do this: > {code:xml} > <iterate entry="node" list="parameters.document['resource/property']"> > <log level="always" message="Property Key: ${node['@key']}"/> > <log level="always" message="First Value: ${node['value[1]']}"/> > </iterate> > {code} -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online. |
Free forum by Nabble | Edit this page |