Project

Profile

Help

Issues with serialize function

Added by Martin Honnen about 7 years ago

At https://martin-honnen.github.io/js/2017/test2017022102.html I have tried to use the XPath @serialize@ function within the @evaluate@ method of the XPath API, however, I don't get the XML representation of nodes but strange results like

    (element ,element )
    ( undefinedn1 undefinedn11 , undefinedn11 undefinedn3 )
    ( undefinedn1 undefinedn11 , undefinedn11 undefinedn3 )

The result always seems to put the items into @()@ although I have explicitly set @method@ as @xml@ and the nodes are not serialized well either, with the @element@ or @undefined@ in there.

The HTML of the page is



	
		<title>Saxon-JS test</title>
		
		<script src="../../Saxon-JS-1.0.0/SaxonJS.min.js"></script>
	<script>		
	function load(url, handler) {
		var req = new XMLHttpRequest();
		req.open('GET', url);
		req.onload = function(evt) {
			handler(req.responseXML);
		};
		req.send();
	} 
	</script>
	<script>
	document.addEventListener('DOMContentLoaded',
		function() {
		  load(
		    'input2017022101.xml', 
		  	function(doc) { 
			  	document.getElementById('input1').textContent = new XMLSerializer().serializeToString(doc);
			  	
			  	var contextNode = SaxonJS.XPath.evaluate('//*[@id="n11"]', doc);
			  	
			  	var links = SaxonJS.XPath.evaluate('let $current := . return //link/a[(source, target) = $current/@id]', contextNode);
			  	
			  	document.getElementById('results').children[0].textContent = SaxonJS.XPath.evaluate('serialize(., map { "method" : "xml", "indent" : true()})', links);
			  	
			  	document.getElementById('results').children[1].textContent = SaxonJS.XPath.evaluate('serialize($links, map { "method" : "xml", "indent" : true()})', doc, { params : { links : links }});
			  	
			  	document.getElementById('results').children[2].textContent = SaxonJS.XPath.evaluate('serialize(let $current := . return //link/a[(source, target) = $current/@id], map { "method" : "xml", "indent" : true()})', contextNode);

		  });
		},
		false
	);
	</script>
			
</head>
<body>
	<section>
		<h1>Saxon-JS test</h1>
		<section>
			<h2>Example input</h2>
			<pre><code id="input1"></code></pre>
		</section>
		<section>
			<h2>Example XPath results</h2>
			<ul id="results">
				<li></li>
				<li></li>
				<li></li>
			</ul>
		</section>
	</section>
</body>

the XML used is





	
		
		
		
		
		
		
		
		
	
	
		n1n2
		n1n11
		n11n3
		n5n5
	



Replies (4)

Please register to reply

RE: Issues with serialize function - Added by John Lumley about 7 years ago

The @serialize()@ function within Saxon-JS 1.0.0 was fleshed out really to help debug the intermediate and result structures in @XPath.evaluate()@, and is not a compliant version - in fact it currently knows nothing about the serialization options at all.

We should have documented this. It is currently being developed, but for the time being is only intended for use in debugging code, and not for generating XML text.

RE: Issues with serialize function - Added by John Lumley about 7 years ago

I'm puzzled why the serialization is showing doubled entries - it may be that for some reason the @$links@ are being doubled. Will investigate.

(The 'undefined' entries are probably associated with text nodes - an area I'm working on in 1.0.0+)

I should emphasise that it will be some time before we have a very-high-compliance version of @serialize()@ in Saxon-JS given the overall complexity of the space. My immediate goal is that you at least get readable XML output for debugging - output that can be successfully reparsed (entities etc.) will be quite some way off.

RE: Issues with serialize function - Added by Martin Honnen about 7 years ago

There are no duplicate entries, the XPath used in the sample selects two different @a@ element nodes in the input document and I am trying to serialize both as one sequence argument to @serialize@, as in @SaxonJS.XPath.evaluate('serialize(let $current := . return //link/a[(source, target) = $current/@id], map { "method" : "xml", "indent" : true()})', contextNode)@.

But now that I know that so far @serialize@ is not implementing the XPath spec but is rather a debugging tool I will resort to the browser's @XMLSerializer@ when wanting to serialize DOM nodes.

RE: Issues with serialize function - Added by John Lumley about 7 years ago

This has proved to uncover a little more than I was anticipating - thank you:

Whilst I said the current @serialize()@ took no account of the options, that isn't quite correct. It didn't take account of the options as a @map()@ value (which is its type when used within an XPath expression), but rather as a Javascript one (there are internal and recursive calls to the subsequent code which use Javascript parameters ...) This in part caused the odd 'undefined' character sequences. I have started to fix this (the serialization parameters can appear either in @map()@ or Javascript property forms) so that some simple options in a map will be supported.

You have however uncovered a somewhat more serious issue. The assignment of @var links@ binds to a sequence of two nodes, and in common with the default strategy for XDM->JS conversion, this is returned as an @Array@ of length 2.

In the first of your subsequent evaluations this is then used as the context item, which was being reconverted into a sequence of length 2, and because the context item wasn't being type checked before it acted as the first argument of serialize (where it is perfectly fine - @serialize($arg as item()*...)@) you got output.

However the type of @$contextItem@ within @XPath.evaluate()@ is @item()?@ so this evaluation, when more than one item was presented, should fail with a cardinality check. (In the second and third of these tests the context item is singular, and the sequence is bound via parameter values which can have multiple arity so execution is OK.)

I have implemented such a check and this will need some more explanation in the documentation - in your case the first example would need a Javascript iteration across each separate member of @links@, serializing and then concatentating the results.

    (1-4/4)

    Please register to reply