[Date Prev]
| [Thread Prev]
| [Thread Next]
| [Date Next]
--
[Date Index]
| [Thread Index]
XPath 2.0 Best Practice Issue: Graceful Degradation
- From: "Costello, Roger L." <costello@mitre.org>
- To: <xml-dev@lists.xml.org>
- Date: Fri, 25 Jan 2008 10:01:22 -0500
Hi Folks,
I submit for your consideration the following XPath 2.0 Best Practice
issue. Please see the questions at the bottom.
[Definition] Graceful degradation is the ability to continue working,
albeit with reduced functionality, when some expected capability is
absent.
ISSUE
How do we design XPath 2.0 statements to degrade gracefully?
EXAMPLE
Consider this snippet of an XML instance document:
<airplane tailnum="C3H1">
<altitude unit="feet">20000</altitude>
</airplane>
An airplane, with tail number C3H1, is flying at an altitude of 20,000
feet.
PROBLEM
Design an XPath statement that specifies this behavior: convert the
altitude value (20000) from feet to meters.
Design the XPath in a way that it specifies a behavior that will
degrade gracefully.
SOLUTION, VERSION #1
Here is one solution to the problem:
//airplane[@tailnum='C3H1']/altitude * .3048
The behavior specified by this XPath statement is: navigate to the
altitude element, atomize its value, and multiply it by .3048
PROBLEM WITH VERSION #1
The XPath statement assumes there exists an airplane element with
tailnum C3H1, and that the airplane has a child element named altitude.
No alternative behavior is specified for the situation in which the
expected elements are absent.
The XPath statement does not degrade gracefully. (More precisely, the
behavior specified by the XPath statement does not degrade gracefully)
SOLUTION, VERSION #2
This XPath statement checks that the expected elements are present:
if (exists(//airplane[@tailnum='C3H1']/altitude)) then
//airplane[@tailnum='C3H1']/altitude * .3048
else
(: behavior to occur when the expected elements are absent :)
The XPath statement specifies a behavior for both the situation where
the expected elements are present, as well as where they are absent.
The XPath statement degrades gracefully ... well, it degrades a bit
gracefully.
PROBLEM WITH VERSION #2
The XPath statement assumes the contents of the altitude element is a
number. No alternative behavior is specified for the situation where
the expected numeric value is absent.
The XPath statement does not degrade as gracefully as we would like.
SOLUTION, VERSION #3
This XPath statement checks that the altitude has a numeric value:
if (exists(//airplane[@tailnum='C3H1']/altitude)) then
if (//airplane[@tailnum='C3H1']/altitude castable as xs:double)
then
//airplane[@tailnum='C3H1']/altitude * .3048
else
(: behavior to occur when the expected numeric value is
absent :)
else
(: behavior to occur when the expected elements are absent :)
The XPath statement specifies a behavior for the cases where the
expected elements are present, where they are absent, where the
altitude value is numeric, and where the altitude value is not numeric.
The XPath statement degrades more gracefully than the prior versions
... but it still can be improved.
PROBLEM WITH VERSION #3
The XPath statement assumes the value of the altitude element is in
feet. No alternative behavior is specified for the situation where the
expected feet value is absent.
The XPath statement does not degrade as gracefully as we desire.
SOLUTION, VERSION #4
This XPath statement checks that the altitude value is in feet:
if (exists(//airplane[@tailnum='C3H1']/altitude)) then
if (//airplane[@tailnum='C3H1']/altitude castable as xs:double)
then
if (exists(//airplane[@tailnum='C3H1']/altitude/@unit))
then
if (//airplane[@tailnum='C3H1']/altitude/@unit =
'feet') then
//airplane[@tailnum='C3H1']/altitude * .3048
else
if (//airplane[@tailnum='C3H1']/altitude/@units =
'meters') then
//airplane[@tailnum='C3H1']/altitude
else
(: behavior to occur when the expected feet
value is absent :)
else
(: behavior to occur when the expected unit attribute
is absent :)
else
(: behavior to occur when the expected numeric value is
absent :)
else
(: behavior to occur when the expected elements are absent :)
The XPath statement specifies a behavior for the cases where the
expected elements are present, where they are absent, where the
altitude value is numeric, where the altitude value is not numeric,
where the unit attribute is present, where the unit attribute is
absent, where the value of the unit attribute is feet, where the value
of the unit attribute is meters, and where the value of the unit
attribute is neither feet or meters.
At last, we have an XPath statement that degrades gracefully.
QUESTIONS
1. Graceful degradation is all about specifying behavior when an
"expected capability" is absent. In the above example, the "expected
capability" is information: elements, attributes, data, and datatypes.
What other types of things might be absent which should be accounted
for?
2. In the above examples I didn't specify the alternate behavior, I
simply wrote a comment. Is it possible to be more specific without
knowledge of the context in which the XPath statement is used?
3. In version #3 I tested the altitude value to see if it has a numeric
value by using the "castable as" operator:
if (//airplane[@tailnum='C3H1']/altitude castable as xs:double)
then
Should I have instead used the "instance of" operator:
if (//airplane[@tailnum='C3H1']/altitude instance of xs:double)
then
What do you recommend?
4. I can't think of any other improvements to the XPath statement to
make it degrade more gracefully. Can you suggest further improvements?
/Roger
[Date Prev]
| [Thread Prev]
| [Thread Next]
| [Date Next]
--
[Date Index]
| [Thread Index]