Bug 36653

Summary: enable a "forking" XSLT task
Product: Ant Reporter: Jens Elkner <elkner>
Component: Core tasksAssignee: Ant Notifications List <notifications>
Status: REOPENED ---    
Severity: enhancement CC: dave.pawson, js, notifications, robert.flaherty, taffy-tyler6464, trevor
Priority: P3    
Version: 1.6.5   
Target Milestone: 1.8.0   
Hardware: All   
OS: All   
Attachments: Resolve xi:include using xslt

Description Jens Elkner 2005-09-14 12:10:25 UTC
Actually, many people wanna use XIncludes in their projects (e.g. for docbook
related stuff), and this requires at least for xalan2, that the System property
key "org.apache.xerces.xni.parser.XMLParserConfiguration" is set to

Since the xslt task does not allow to set system properties temporarily, another
option is need - the invocation of ant with -D... is a bad workaround, since
than all task would see/use this value. 

So one option would be, to allow a parser.config attribute, where one could set
appropriate value.

Even easier, if the processor is xalan2 aka trax, allow an attribute
"xinclude={on|off}" and if on, just set the system property as described above
and reset it to its original value, when the task is finished ...
Comment 1 Stefan Bodewig 2008-11-24 08:38:17 UTC
*** Bug 31331 has been marked as a duplicate of this bug. ***
Comment 2 Stefan Bodewig 2008-11-24 08:51:34 UTC
*** Bug 44831 has been marked as a duplicate of this bug. ***
Comment 3 Stefan Bodewig 2008-11-26 06:46:11 UTC
svn revision 720892 allows setting of arbitrary system properties during processing.

<xslt ...>
    <sysproperty key="org.apache.xerces.xni.parser.XMLParserConfiguration"

should have the desired effect.
Comment 4 Trevor Harmon 2008-12-02 20:02:03 UTC
More details on the Saxon side of this can be found here:

Comment 5 Stefan Bodewig 2008-12-03 01:43:21 UTC
> or to set the attribute denoted by FeatureKeys.XINCLUDE to Boolean.TRUE
> on the TransformerFactory.

together with http://www.saxonica.com/documentation/javadoc/constant-values.html#net.sf.saxon.FeatureKeys.XINCLUDE

would correspond to

<xslt ...>
    <param name="http://saxon.sf.net/feature/xinclude-aware"

but the system property should also work.

I don't think the task is lacking any features that would prevent you from using
XInclude with either Saxon or Xalan.
Comment 6 Stefan Bodewig 2008-12-03 01:48:11 UTC
replace param with attribute in comment #5
Comment 7 Trevor Harmon 2008-12-03 07:11:07 UTC
I'm trying out the current Ant 1.8.0 nightly build with Saxon-B, but I still can't Xinclude to work. I've tried both the <factory> and the system property techniques, but it's simply ignoring my <xi:include> directives. Any suggestions?
Comment 8 Stefan Bodewig 2008-12-04 01:30:56 UTC
On second thought the system property approach may be failing because saxon is started in the same VM that runs Ant and ends up using the same Xerces which could be ignoring the system property because it had a different value when Ant started (it might evaluate the property only once).

Depending on what Saxon does when the attribute is set, it may fail to enable XInclude for the same reason (Xerces started without XInclude and isn't willing to change).

I'm not sure what we can do short of adding a fork mode to <xslt> which doesn't look like a trivial task at first glance.
Comment 9 Trevor Harmon 2008-12-13 12:57:54 UTC
Actually, I think the problem is more serious than that. Xinclude still doesn't work even if you work around the issue in comment #8 by setting the system property ahead of time.

Using the current Ant trunk, I started out by setting ANT_OPTS="-Dorg.apache.xerces.xni.parser.XMLParserConfiguration=org.apache.xerces.parsers.XIncludeParserConfiguration". This has the desired effect of changing Xerces to use XIncludeParserConfiguration instead of the default XIncludeAwareParserConfiguration. I've confirmed this through debugging. XIncludeParserConfiguration is definitely being instantiated with this setting.

Next, since I'm using Saxon 9.1, I added this nested element to my <xslt> task:

  <factory name="net.sf.saxon.TransformerFactoryImpl">
      <attribute name="http://saxon.sf.net/feature/xinclude-aware" value="true"/>

This is where problems start. Adding the above factory attribute causes org.apache.xerces.xni.parser.XMLConfigurationException.

I've done some debugging to find out why this is being thrown, and I can see that Saxon is definitely trying to configure the parser for Xinclude. The sendSAXSource method in its Sender.java is making this call:

  parser.setFeature("http://apache.org/xml/features/xinclude-aware", true);

But when this call propagates to Xerces, its ParserConfiguration.java looks in its list of recognized feature strings, doesn't find "http://apache.org/xml/features/xinclude-aware", and throws XMLConfigurationException.

Actually, this is to be expected because the current Ant trunk is bundled with the Xerces 2.9.0 parser, and that version doesn't know about "http://apache.org/xml/features/xinclude-aware". It only knows about "http://apache.org/xml/features/xinclude". (Not sure why.)

Saxon attempts to handle this gracefully, as shown in this snippet from its Sender.java:

  boolean tryAgain = false;
  try {
      // This feature name is supported in the version of Xerces bundled with JDK 1.5
      parser.setFeature("http://apache.org/xml/features/xinclude-aware", true);
  } catch (SAXNotRecognizedException err) {
      tryAgain = true;
  } catch (SAXNotSupportedException err) {
      tryAgain = true;
  if (tryAgain) {
      try {
          // This feature name is supported in Xerces 2.9.0
          parser.setFeature("http://apache.org/xml/features/xinclude", true);
      } catch (SAXNotRecognizedException err) {
      } catch (SAXNotSupportedException err) {
Unfortunately, this failover technique does not work, apparently due to a Xerces problem. When Xerces encounters the unrecognized feature string in its ParserConfigurationSettings.checkFeature method, it throws its own proprietary org.apache.xerces.xni.parser.XMLConfigurationException. I don't know why it doesn't use the standard org.xml.sax.SAXNotRecognizedException or org.xml.sax.SAXNotSupportedException. It is either a bug in Saxon (because it catches the wrong exception) or a bug in Xerces (because it throws the wrong exception).

In this case, though, it doesn't actually matter because even if Saxon specified "xinclude" instead of "xinclude-aware", it still wouldn't work. That's because the feature list variable in Xerces doesn't contain either one! When ParserConfigurationSettings.checkFeature is called, I see that "http://apache.org/xml/features/xinclude/fixup-base-uris" and "http://apache.org/xml/features/xinclude/fixup-language" are there, but "http://apache.org/xml/features/xinclude" is not.

So the root of this problem is that Xerces is not adding "http://apache.org/xml/features/xinclude" to its feature list. I even tried to add it explicitly in Ant's TraXLiaison.getSource methods:

  spFactory.setFeature("http://apache.org/xml/features/xinclude", true);



But they simply cause javax.xml.parsers.ParserConfigurationException to be thrown in org.apache.xerces.jaxp.SAXParserFactoryImpl.newSAXParser.

So now I'm basically stuck, but I hope that the analysis above might help someone.

Comment 10 Remie Bolte 2008-12-15 08:28:51 UTC
Created attachment 23023 [details]
Resolve xi:include using xslt

Since the XInclude standard is pretty simple, you can also just implement your own xi:include resolver using XSLT and XPath (see attachment).

This is a very basic implementation: it only supports the xpointer attribute to resolve an element based on a match with the xml:id attribute.

It is probably not as perfect as using the XInclude resolving methods of the xslt parsers (although i have found that those implementation also differ in regard to the xpointer, so personally I like to use the snippet for it gives me more flexibility in my projects).
Comment 11 Stefan Bodewig 2008-12-18 05:40:41 UTC
(In reply to comment #9)
> Actually, I think the problem is more serious than that. Xinclude still doesn't
> work even if you work around the issue in comment #8 by setting the system
> property ahead of time.

I agree that if it doesn't work that way then we are out of luck on the Ant side (but we should make it possible to get as close as we can).  This means we should implement a fork-option in <xslt>, IMHO.

It would be nice if you took your findings here and reported bugs against Xerces-J and Saxon respectively.