Fixing the XML wrapper regarding the existence ops - Was: Handling missing node values with NodeModel
Daniel Dekany <[email protected]>
| Newsgroups | gmane.comp.web.freemarker.user,gmane.comp.web.freemarker.devel |
|---|---|
| Message-ID | <[email protected]> |
Tuesday, June 21, 2011, 4:36:26 PM, Tom Fennelly wrote:
> Awesome..... that worked perfect... thanks Daniel !!!!
No, it's in fact awful, but this is how it is for now. I see two ways
out of this situation:
a) Introduce a marker (empty) interface, freemarker.template.DefaultValue.
If a TemplatModel implements this interface, that tells FreeMarker
that this value is to be used only as the last chance, and the
locally provided default (like "anonymous" in name!"anonymous")
should take precedence. This feature would be, coincidentally,
useful for XML, because if empty XPath result sets are marked with
DefaultValue, then something like myXmlNode.foo!"default" would
magically work, just like myXmlNode.foo[0]!"default" does. However,
the empty results set is not "last chance" value (not a default
value), so it's kind of a dirty trick.
b) When people write myXmlNode.foo, they either expect 1 or 0 matches
(a single node which is optional), or multiple matches (a list of
nodes, even if possibly 0 or 1 long). XPath however doesn't have a
notation to express these two intents, so the current XML wrapper
doesn't have either. This is mathematically nice and everything,
but in practice it leads to all those voodoo tricks (like if and
only if myXmlNode.foo returns 1 matching node, the result is both a
scalar and a sequence - explain that to Average Joe Jr.) and
confusion. So, how about making these two cases different like:
- myXmlNode.foo means "I want that *single* node". If there are no
matches, that's a undefined variable error, thus `!`, `??` etc.
works as expected. If there are multiple marching nodes, that's a
TemplateModelException, that can't be suppressed (except with
#attempt, of course).
- myXmlNode.foo$ means "I want the list of the matching nodes".
This would always return a sequence, even if 0 long. Why "$"?
It could be read as the "S" of the plural form, "foos". (I think
this was originally the idea of Jonathan.) The drawback is of
course that this way we deviate from XPath, so XPath expression
couldn't be written as myXmlNode["foo//bar"] and like. Instead,
they had to be written as myXmlNode("foo//bar") maybe.
Neither of these are strictly backward-compatible, but since we can
have multiple wrapper instances and instances can be configured or of
different classes, that's manageable.
Another thing... I find it scary that we depend on internal API-s to
do XPath with Xerces. If they still haven't added the required API-s
as public, well... in the new wrapper we should just require Jaxen.
Unless, there are performance problems with that or like... anybody is
aware of such issues?
--
Best regards,
Daniel Dekany
> On 21/06/2011 15:29, Daniel Dekany wrote:
>> I recommend reading this:
>>
>> http://freemarker.org/docs/xgui_imperative_learn.html
>>
>> It answers this question among others. Anyway, you could do it like
>> this:
>>
>> ${.vars["com.acme.Travel"].checkIn[0]!}
>>
>> The relevant change I did here is the adding of [0]; the others are
>> just aesthetical. You see, the result of the XPath query exists even
>> if it's an empty node list, so what you want to know if it has a 1st
>> element.
>>
>>
>> Tuesday, June 21, 2011, 3:26:15 PM, Tom Fennelly wrote:
>>
>>> Hi.
>>>
>>> I'm using a NodeModel and was wondering how missing nodes can be
>>> handled? I'm looking for the equivalent of the
>>> unsafe_expr!default_expr notation
>>> (http://freemarker.sourceforge.net/docs/dgui_template_exp.html#dgui_template_exp_missing),
>>> but something that works for NodeModels (the default did not work for me).
>>>
>>> BTW.. the template's in question use the .vars syntax in the
>>> expressions. So, when I do the following I get an exception -
>>> ${.vars["com.acme.Travel"]["checkIn"]!""}. The exception is...
>>> Expecting a string, date or number here, Expression
>>> .vars["com.acme.Travel"]["checkIn"]!"" is instead a freemarker.ext.dom.NodeListModel
>>> The problematic instruction:
>>> ----------
>>> ==> ${.vars["com.acme.Travel"]["checkIn"]!""} [on line 3,
>>> column 19 in free-marker-template]
>>> ----------
>>>
>>> Java backtrace for programmers:
>>> ----------
>>> freemarker.core.NonStringException: Error on line 3, column 21 in free-marker-template
>>>
>>> Thanks in advance.
>>>
>>> T.
>
> ------------------------------------------------------------------------------
> EditLive Enterprise is the world's most technically advanced content
> authoring tool. Experience the power of Track Changes, Inline Image
> Editing and ensure content is compliant with Accessibility Checking.
> http://p.sf.net/sfu/ephox-dev2dev
> _______________________________________________
> FreeMarker-user mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/freemarker-user
>
------------------------------------------------------------------------------
EditLive Enterprise is the world's most technically advanced content
authoring tool. Experience the power of Track Changes, Inline Image
Editing and ensure content is compliant with Accessibility Checking.
http://p.sf.net/sfu/ephox-dev2dev