DocumentBuilder.Build closes passed stream
Added by Anonymous over 14 years ago
Legacy ID: #8230519 Legacy Poster: Jürgen Bayer (daraca)
I use Saxon HE 9.2.0.6. If I pass a stream to DocumentBuilder.Build, the Build method closes the stream. This is not a good behaviour since the stream may be used elsewhere after passing it to Build. In my case I wanted to first validate an XML document using the Schematron styleshets over Saxon and validate it after that using the .NET build in functions for XML Schema (I know that I could use Saxon EE, but I must use Saxon HE).
Replies (3)
Please register to reply
RE: DocumentBuilder.Build closes passed stream - Added by Anonymous over 14 years ago
Legacy ID: #8231083 Legacy Poster: Michael Kay (mhkay)
Saxon's general policy is that Saxon should close a stream only if Saxon created/opened it. And there's a lot of code that tries hard to follow that policy, but it's hard to check all possible paths, and closing streams that shouldn't be closed, and not closing them when they should, are both perennial problems. There are also a few cases where the policy is deliberately broken, for example in compile-and-go interfaces where a single method call does both stylesheet compilation and execution, you don't want to keep the input stream holding the stylesheet open for the duration of the transformation. In the case of this particular interface, it may be that the XML parser is closing the stream, in which case there's not much I can do about it. (I could wrap the supplied stream in a stream of my own so that when the XML parser closes my stream, it doesn't close yours; but that's just too complicated.) I will investigate further. Do you have any option settings on the DocumentBuilder or Processor that would cause it to use the Microsoft XML parser rather than the Xerces parser? I'm a bit puzzled by your rationale, however. Even if Saxon doesn't close the stream, it will still consume it:
RE: DocumentBuilder.Build closes passed stream - Added by Anonymous over 14 years ago
Legacy ID: #8233873 Legacy Poster: Jürgen Bayer (daraca)
Thanks for your reply. I did not set any settings that would cause the DocumentBuilder to use Microsoft XML (I suppose, DocumentBuilder uses the Xerces parser by default). My rationale is the following: I have an XML 1.0 Schema with embedded Schematron parts. Since I am restricted to use Saxon HE (not EE), I need to validate the XML Schema 1.0 part using .NET classes (XmlValidatingReader). Since the Schematron part uses XPath 2.0 features, I need to use Saxon to compile the Schematron XSLT files and get a result from that. In both cases I want to use a stream for the XSD file containing both the XML Schema and the Schematron assertions. Here is my Saxon related code: private static MemoryStream TransformDocumentStream(Stream documentStream, Stream xsltStream) { MemoryStream resultStream = new MemoryStream(); documentStream.Position = 0; Processor processor = new Processor(); DocumentBuilder documentBuilder = processor.NewDocumentBuilder(); documentBuilder.BaseUri = new Uri("http://www.dummy.com"); // Build checks whether BaseUri is null XdmNode input = documentBuilder.Build(documentStream); var xsltCompiler = processor.NewXsltCompiler(); XsltTransformer transformer = xsltCompiler.Compile(xsltStream).Load(); transformer.InitialContextNode = input; Serializer serializer = new Serializer(); StreamWriter outputWriter = new StreamWriter(resultStream); serializer.SetOutputWriter(outputWriter); transformer.Run(serializer); resultStream.Position = 0; return resultStream; }
RE: DocumentBuilder.Build closes passed stream - Added by Anonymous over 14 years ago
Legacy ID: #8234000 Legacy Poster: Michael Kay (mhkay)
It does seem to be Xerces that's closing the input stream. When run with the Microsoft parser using processor.SetProperty("http://saxon.sf.net/feature/preferJaxpParser", "false"); the stream appears to be left open: I don't know if that gives you a way forward. In principle I could intercept Xerces' call to close the stream (because all the stream operations go through my code, which maps Java stream operations to .NET stream operations). However, I think this has a very high chance of having unwanted side-effects. As an alternative, you could consider doing this yourself: pass an implementation of Stream that passes all calls unchanged to an underlying Stream, except for the Close() call.
Please register to reply