XSL:If different in MSXML4 and Saxon also between server and

Here should go questions about transforming XML with XSLT and FOP.
GraemeBryce
Posts: 12
Joined: Tue Mar 21, 2006 12:06 pm

XSL:If different in MSXML4 and Saxon also between server and

Post by GraemeBryce » Tue Mar 21, 2006 12:12 pm

I have the following code

Code: Select all


<xsl:if test="(not(@allowpaging))">
<xsl:call-template name="paging" />
</xsl:if>
this works as I would expect when run server side using MSXML4 on .NET by testing true only when the allowpaging attribute actually exists on the current node.

It also operates as expected when using Saxon in Oxygen, however if I us MSXML4 in Oxygen the test always returns false.

If I alter the test to

Code: Select all


<xsl:if test="(not(node()/@allowpaging))">
then all is well

Can anyone explain?

My thanks

Graeme

george
Site Admin
Posts: 2101
Joined: Thu Jan 09, 2003 2:58 pm

Re: XSL:If different in MSXML4 and Saxon also between server

Post by george » Tue Mar 21, 2006 12:57 pm

GraemeBryce wrote:[...]
<xsl:if test="(not(@allowpaging))">
[...]
this works as I would expect when run server side using MSXML4 on .NET by testing true only when the allowpaging attribute actually exists on the current node.
[...]
The test does exactly the opposite, it will return true if the atttribute does not exist on the current node.

Anyway, it helps in general to get cut down samples to reproduce the problem. I tested with a simple stylesheet like below and I get similar results with both MSXM4 and Saxon in oXygen:

Code: Select all


<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/test">
<xsl:if test="(not(@allowpaging))">
<xsl:call-template name="paging"/>
</xsl:if>
</xsl:template>

<xsl:template name="paging">
[in paging]
</xsl:template>
</xsl:stylesheet>
input is

Code: Select all


<test/>
Best Regards,
George

GraemeBryce
Posts: 12
Joined: Tue Mar 21, 2006 12:06 pm

Post by GraemeBryce » Tue Mar 21, 2006 5:52 pm

George

Indeed it does help to get a cut down example and I thought that was what I had done, however I appear to have confused myself!

Your test does of course work and I am now back in the more complex code I have and trying to work out what exactly I have done wrong.

Many thanks for your prompt reply, If I remain unable to deal with the full example I will post again with an appropriate test.

Cheers

GraemeBryce
Posts: 12
Joined: Tue Mar 21, 2006 12:06 pm

Post by GraemeBryce » Tue Mar 21, 2006 7:37 pm

George

I have now been able to track down the specific problem and replicate it in a test case.

It related to the use of attributes defined as "fixed" in the XSD

I have the following test files

TEST.XML

Code: Select all


<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test.xsd">
<content>
<section>
<datablock id="aaa" >
<columns>
<column id="EntityID" />
<column id="Name" />
<column id="Description" />
</columns>
</datablock>
</section>
</content>
</root>

TEST.XSD

Code: Select all


<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">



<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element ref="content"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>


<xs:element name="content">
<xs:complexType>
<xs:sequence>
<xs:element ref="section"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="section">
<xs:complexType>
<xs:sequence>
<xs:element ref="datablock"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="datablock">
<xs:complexType>
<xs:sequence>
<xs:element ref="columns"/>
</xs:sequence>
<xs:attribute name="id" use="required" type="xs:NCName"/>
<xs:attribute name="allowpaging" fixed="false" />
</xs:complexType>
</xs:element>
<xs:element name="columns">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="column"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="column">
<xs:complexType>
<xs:attribute name="id" use="required" type="xs:NCName"/>
</xs:complexType>
</xs:element>



</xs:schema>
TEST.XSL

Code: Select all


<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output indent="yes" method="xml" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" omit-xml-declaration="yes"
encoding="utf-8" />

<xsl:template match="datablock[columns]">
<table border="1">
<xsl:if test="not(@allowpaging='false' )">
<xsl:call-template name="paging" />
</xsl:if>
<tr>
<td class="body">
<table border="1">
<tr>
<xsl:apply-templates />
</tr>
</table>
</td>
</tr>
</table>
</xsl:template>


<xsl:template name="paging">
<tr>
<td>[in paging]</td>
</tr>
</xsl:template>

<xsl:template match="column">
<td><xsl:value-of select="@id"/></td>
</xsl:template>


</xsl:stylesheet>
STEPS TO REPLICATE

With the files EXACTLY as above (ie there is no allowpaging attribute in <datablock>) then with MSXML4 the [paging] template is not called wilst with Saxon 6.5 it is called.

The issue appears to relate to the use of FIXED within the allowpaging attribute definition in the XSD - alter this to an attribute simply of type xs:boolean and MSXML4 then agrees with Saxon.

What is strange is that it is the alteration in the XSD rather than any change in the XML or XSL that causes the problem.

Equally (and not surprisingly) removing the declaration for the XSD at the top of the XML has the same effect.

I would appreciate a note if anyone can a)replicate the problem and b)explain it.

we have however identified a WORKAROUND.

Leaving the XML and XSD exactly as shown above it is possible to alter the syntax of the test in the XSL to read as follows

Code: Select all


<xsl:if test="not(node()/@allowpaging='false' )">
As far as I am aware this should mean the same thing as the original syntax, however with the adjustment both Saxon and MSXML correctly assemble the output.

Regards: Graeme

george
Site Admin
Posts: 2101
Joined: Thu Jan 09, 2003 2:58 pm

Post by george » Wed Mar 22, 2006 1:17 pm

Hi,

Your workaround is not ok, as it checks not to be such an attribute on any of the children elements of the datablock element, so this works only in this example but will give you a different result if you specify the allowpaging with the value false in the datablick element.

What happens is that when the transformation is performed with MSXML 4.0 the source is the XML with the XML Schema default/fixed attributes added. On the .NET XSLT processor I was able to control that through the Oxygen->Preferences -- XML --- XSLT/FO/XQuery -- XSLT -- MSXSL.NET -- Validate documents during parse phase option. Although there is a similar option for the MSXSL processor it seems that MSXSL 3.0 does not add the fixed attributes even if the validation of the source is enabled while the MSXSL 4.0 always adds the fixed attributes even if the source validation is disabled.

Now, a workaround for your case. If there is no attribute defined then you should not allow paging - this is what the schema says. So you should change the test as

Code: Select all


         <xsl:if test="@allowpaging and not(@allowpaging='false')">
<xsl:call-template name="paging" />
</xsl:if>
and you should get similar results with all processors.

Best Regards,
George

GraemeBryce
Posts: 12
Joined: Tue Mar 21, 2006 12:06 pm

Post by GraemeBryce » Wed Mar 22, 2006 2:27 pm

George

Again my thanks for the reply.

I will proceed with the syntax you suggest.

It deals appear odd that MSXML is adding FIXED attributes. I can fully appreciate why the parser adds a DEFAULT attribute as this exists in the schema for that reason.

However it would appear to be an error to add a FIXED attribute that is not already in the XML as the XSD definition surely suggest that it can have only one value and failing that it must not exist.

Thus the difference between fixed="false" and type="xs:boolean" is that in the first case the possible values and null(i.e. the attribute is not there) and "false", whilst in the second there are three possible values being null, true, false.

The lesson we have taken from this is that use of FIXED attributes may cause as many problems as it solves.

I am grateful for your time and detail on this matter and hope others benefit from this thread.

Regards: Graeme

george
Site Admin
Posts: 2101
Joined: Thu Jan 09, 2003 2:58 pm

Post by george » Wed Mar 22, 2006 3:10 pm

My reading of the schema spec is a little different with respect to fixed values. Fixed values are basically default values with an additional constraint, if present they must be that specified value:

http://www.w3.org/TR/xmlschema-1/#a-value_constraint
***
{value constraint} reproduces the functions of XML 1.0 default and #FIXED attribute values. default specifies that the attribute is to appear unconditionally in the ·post-schema-validation infoset·, with the supplied value used whenever the attribute is not actually present; fixed indicates that the attribute value if present must equal the supplied constraint value, and if absent receives the supplied value as for default. Note that it is values that are supplied and/or checked, not strings.
***

However, the XSLT 1.0 specification does not have any reference to post schema validation infoset so the bahaviour here is probably implementation dependent. For XSLT 2.0 things are better specified and there are a lot of references to the post schema validation infoset but the validation and thus the addition of default/fixed attributes are required only for XSLT 2.0 schema aware processors when they perform a validation of the input source. I just tested with Saxon 8 SA and if I configure it to validate the input it adds defaut values. However it does not add fixed values and I believe this is a bug although the XSLT 2.0 specification refers only default values as required to be added but from the above quote from the XML Schema specification fixed values are default values with an additional constraint:

http://www.w3.org/TR/xslt20/#validation-process
***
As well as checking for validity against the schema, the validity assessment process causes type annotations to be associated with element and attribute nodes. If default values for elements or attributes are defined in the schema, the validation process will where necessary create new nodes containing these default values.
***

Best Regards,
George

Post Reply