Currently I am working on diploma thesis, in which I have implemented WS-Transfer extension WS-Transfer Implementation details. The specification defines four types of possible messages, which can be used to create, update, delete or get XML documents from server. The documents are called XML resources. The extension also allows working with just fragments of these resources. For example, on the server there is saved the XML resource, which contains complete information about employee of some company. The whole resource has non-trivial size, but we want to get information just about his age. For this purpose the extension allows identify a subset of resource. It defines a dialect attribute, which determines IRI of extension, which will be used for getting of resource fragment. Subsequently, the specification says that if the dialect attribute is set to "http://www.w3.org/2011/03/ws-fra", the resource must be processed as specified by the WS-Fragment specification. In other words, the WS-Fragment dialect must be supported.
Based on the above, after finishing the main part of WS-Transfer implementation, I have started to implement the WS-Fragment specification. During the implementation, I encountered with problems how to implement some parts of the specification with current technologies in Java. Concurrently I think that I found examples, which are incorrect or the attached XML schema not allowed such examples. Intent of this document is to describe these problems or uncertainties and open a discussion about them.
1 XML Schema of WS-Fragment
1.1 In the XML Schema is defined a Expression element, which has type ExpressionType. ExpressionType is defined as ComplexType, which can contain any sequence of any elements. The problem is that it can contain only the elements and so the examples are not valid with this definition, because they insert a TextNode into the Expression instead of the Element. To enable mix elements with text content, the ComplexType, which defines the Expression type, must have Mixed attribute set on true.
- <xs:complexType name='ExpressionType'>
+ <xs:complexType name='ExpressionType' mixed="true">
1.2 There are also examples, which show how to send a Put request containing WS-Fragment dialect. The specification says that the Expression element can contain a Mode attribute, but it is not defined in the XML schema. It is true that the Expression element is also used in the Get request, which does not require this attribute. Is it intention that the attribute is not in the XML schema?
2 Fragment Serialization
The specification says that the Expression must evaluate to one of four types: a Node-set, a Boolean, a Number or a String. A node-set is zero or more elements, attributes or text values of elements. Element nodes in a node-set are serialized directly into their XML representation. Serialization of an attribute node separates the name from the value using the AttributeNode element. The TextNode element is used to serialize a text node (WS-Fragment, sec 4.2). However, there is not any mention for Boolean, Number and String. The only information about them is that the Boolean should be converted as xs:boolean, the Number as xs:double and the String as xs:string. There is not any example or detailed description, which shows situation, when Boolean, Number or String is returned. What is the correct form of such response? The specification says that the result should be wrapped in the Value element, but if the returned value is inserted directly into the Value element, it occurs the same problems mentioned in section 1.1.
3 Identification of a Resource Subset
WS-Fragment defines an attribute Language, which specifies how will be the expression interpreted. Subsequently it defines two languages, which must be supported – QName and XPath.
"The QName expression language is a syntax for expressions that uses a single QName to reference the immediate children of the root element of the resource representation. The expression MUST evaluate to zero or more elements, each including the element name, any attributes and its entire content. This language can be implemented as a precise subset of the XPath 1.0 language." (WS-Fragment, sec. 6)
"The XPath 1.0 expression language uses an XPath to reference specific fragments of the resource representation. The XPath is logically applied to the XML representation of the resource and the result of the XPath is returned as the value for that expression. This language is useful for resources with full XPath processing capability or which need to support returning values computed from their resource representation." (WS-Fragment, sec. 7)
"Except in the cases listed below, the Expression MUST evaluate to a single node within the representation. This avoids any issues that might occur due to updating multiple portions of a resource within one invocation - in other words, "batching" is prohibited. There are however a few special cases that need to be taken into account:
- An Expression that evaluates to the root of the resource representation might not result in any nodes being returned from the Expression processor. For example, an XPath expression of "/" on an empty resource would return an empty node-set. However, to allow for requesters to specify the root (implying the entire document), Expression Languages (and supporting services) that wish to support this concept might need to make special allowances for this situation. Each Expression Language would need to call out this special expression.
- While WS-Fragment doesn't support batching, there are times when a requester might need to act upon an entire sequence of elements (i.e. a list of elements of the same QName that are all siblings). For example, a requester wanting to delete all children of an element. Rather than requiring the requester to send a series of WS-Transfer Put requests to delete each individual child element, WS-Fragment allows for Expression Languages (and services) to identify and act upon the sequence as one entity.
If an Expression does evaluate to more than one node then, except for the cases listed above, the implementation MUST process only the first selected node." (WS-Fragment, sec. 4.1)
Consider the following situation. We send the request with expression "person" written in the QName language. The server should return all children of the root element, because QName references to the immediate children of the root element. So if we send the request with expression "children" we get empty response. It is clear, but what happens if we send expression "//person" written in the XPath language? The result will contain all person elements, which are in the resource, but the server should return only the first selected node, because person on the line 8 has not same parent element as person elements on lines 2 and 5. How can we distinguish between this situation and the situation when we use "/persons/person" expression? The resulted elements of the second expression will have the same QName and they also will have the same parent, so the server should return all selected nodes. The question is how to implement it. My suggestion is to evaluate the XPath and then check the resulted node list if it meets the mentioned requirements. Is this correct way?
4 XPath in the Put request
The specification gives examples of Put requests with different initial representation, mode, expression, value and it also gives expected results, but some of them are difficult to implement. The common problem of these examples is that the given XPath expression points to a non-existing node. Consider following example:
4.1. In the specification it is written that the Replace mode has the net effect of doing a "delete" on the referenced fragment, followed by an "insert" on the fragment's parent. If the Expression evaluates to an empty fragment then the "delete" portion of the operation MUST have no effect (WS-Fragment, sec. 4.4). However the specification also says that the Expression MUST evaluate to a single node except few special cases, which I discuss in the section 3. Is the evaluation to an empty fragment special case?
4.2 Let us consider that the evaluation to an empty fragment is special case. So we evaluate the XPath expression "/a/b" on the XML document "<a/>". The XPath evaluator in Java returns null value. Expression was evaluated to an empty fragment so the "delete" operation won't have any effect, but how to get pointer on the parent node from null value? Other possibility is to modify given XPath expression in such way that it evaluates to the parent node, but how to do it? What should be correct response if we sent "//b" expression? How can we distinguish between these two expressions?
|/ or /*
Note: The element <a'> is meant as a different instance of the same type.
4.3. The Add mode indicates that the children of the Value element MUST be added to the resource representation relative to the fragment referenced by the children of the Expression element (WS-Fragment, sec. 4.4). In the above example the expression "/" evaluates to the whole document, which can have at most one child, so the adding of the second child generates fault. However the expression "/*" evaluates to <a/> element and the final representation should be <a><a'/></a>.