From: Oleg T. <he...@us...> - 2004-10-28 18:27:16
|
Update of /cvsroot/mvp-xml/XInclude/v1/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17915/v1/src Modified Files: SR.resx TextIncludingReader.cs XInclude.csproj XIncludingReader.cs Log Message: Fixing bugs. Implemented non-streaming mode for text inclusion. Index: XInclude.csproj =================================================================== RCS file: /cvsroot/mvp-xml/XInclude/v1/src/XInclude.csproj,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- XInclude.csproj 28 Oct 2004 13:01:51 -0000 1.7 +++ XInclude.csproj 28 Oct 2004 18:27:05 -0000 1.8 @@ -211,6 +211,12 @@ BuildAction = "Compile" /> <File + RelPath = "Common\XPath\IHasXPathNavigator.cs" + Link = "..\..\..\Common\v1\src\XPath\IHasXPathNavigator.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "Common\XPath\IndexingXPathNavigator.cs" Link = "..\..\..\Common\v1\src\XPath\IndexingXPathNavigator.cs" SubType = "Code" Index: XIncludingReader.cs =================================================================== RCS file: /cvsroot/mvp-xml/XInclude/v1/src/XIncludingReader.cs,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- XIncludingReader.cs 28 Oct 2004 13:01:51 -0000 1.17 +++ XIncludingReader.cs 28 Oct 2004 18:27:05 -0000 1.18 @@ -3,6 +3,7 @@ using System; using System.Xml; using System.Xml.Schema; +using System.Xml.XPath; using System.IO; using System.Net; using System.Text; @@ -10,6 +11,7 @@ using System.Collections; using Mvp.Xml.Common; +using Mvp.Xml.Common.XPath; using Mvp.Xml.XPointer; #endregion @@ -68,7 +70,9 @@ //XmlResolver to resolve URIs XmlResolver _xmlResolver; //Expose text inclusions as CDATA - private bool _exposeTextAsCDATA; + private bool _exposeTextAsCDATA; + //Work in streaming mode (no support for intra-document references) + private bool _streamingMode = true; #endregion #region Constructors @@ -76,9 +80,12 @@ /// Creates new instance of <c>XIncludingReader</c> class with /// specified underlying <c>XmlReader</c> reader. /// </summary> - /// <param name="reader">Underlying reader to read from.</param> - public XIncludingReader(XmlReader reader) + /// <param name="reader">Underlying reader to read from</param> + /// <param name="streamingMode">Work in streaming mode</param> + /// <remarks>Note: intra-document references are not supported in streaming mode.</remarks> + public XIncludingReader(XmlReader reader, bool streamingMode) { + _streamingMode = streamingMode; XmlTextReader xtr = reader as XmlTextReader; if (xtr != null) { @@ -89,10 +96,26 @@ ValidationCallback); _normalization = xtr.Normalization; _whiteSpaceHandling = xtr.WhitespaceHandling; - _reader = vr; + + if (_streamingMode) + _reader = vr; + else + { + //In-memory mode + _reader = CreateInMemoryReader(vr); + } } - else - _reader = reader; + else + { + if (_streamingMode) + _reader = reader; + else + { + //In-memory mode + _reader = CreateInMemoryReader(reader); + } + } + _nameTable = reader.NameTable; Init(); } @@ -102,8 +125,125 @@ /// specified URL. /// </summary> /// <param name="url">Document location.</param> + /// <param name="streamingMode">Work in streaming mode</param> + /// <remarks>Note: intra-document references are not supported in streaming mode.</remarks> + public XIncludingReader(string url, bool streamingMode) + : this(new XmlBaseAwareXmlTextReader(url), streamingMode) {} + + /// <summary> + /// Creates new instance of <c>XIncludingReader</c> class with + /// specified URL and nametable. + /// </summary> + /// <param name="url">Document location.</param> + /// <param name="nt">Name table.</param> + /// <param name="streamingMode">Work in streaming mode</param> + /// <remarks>Note: intra-document references are not supported in streaming mode.</remarks> + public XIncludingReader(string url, XmlNameTable nt, bool streamingMode) : + this(new XmlBaseAwareXmlTextReader(url, nt), streamingMode) {} + + /// <summary> + /// Creates new instance of <c>XIncludingReader</c> class with + /// specified <c>TextReader</c> reader. + /// </summary> + /// <param name="reader"><c>TextReader</c>.</param> + /// <param name="streamingMode">Work in streaming mode</param> + /// <remarks>Note: intra-document references are not supported in streaming mode.</remarks> + public XIncludingReader(TextReader reader, bool streamingMode) + : this(new XmlBaseAwareXmlTextReader(reader), streamingMode) {} + + /// <summary> + /// Creates new instance of <c>XIncludingReader</c> class with + /// specified URL and <c>TextReader</c> reader. + /// </summary> + /// <param name="reader"><c>TextReader</c>.</param> + /// <param name="url">Source document's URL</param> + /// <param name="streamingMode">Work in streaming mode</param> + /// <remarks>Note: intra-document references are not supported in streaming mode.</remarks> + public XIncludingReader(string url, TextReader reader, bool streamingMode) + : this(new XmlBaseAwareXmlTextReader(url, reader), streamingMode) {} + + /// <summary> + /// Creates new instance of <c>XIncludingReader</c> class with + /// specified <c>TextReader</c> reader and nametable. + /// </summary> + /// <param name="reader"><c>TextReader</c>.</param> + /// <param name="nt">Nametable.</param> + /// <param name="streamingMode">Work in streaming mode</param> + /// <remarks>Note: intra-document references are not supported in streaming mode.</remarks> + public XIncludingReader(TextReader reader, XmlNameTable nt, bool streamingMode) : + this(new XmlBaseAwareXmlTextReader(reader, nt), streamingMode) {} + + /// <summary> + /// Creates new instance of <c>XIncludingReader</c> class with + /// specified URL, <c>TextReader</c> reader and nametable. + /// </summary> + /// <param name="reader"><c>TextReader</c>.</param> + /// <param name="nt">Nametable.</param> + /// <param name="url">Source document's URI</param> + /// <param name="streamingMode">Work in streaming mode</param> + /// <remarks>Note: intra-document references are not supported in streaming mode.</remarks> + public XIncludingReader(string url, TextReader reader, XmlNameTable nt, bool streamingMode) : + this(new XmlBaseAwareXmlTextReader(url, reader, nt), streamingMode) {} + + /// <summary> + /// Creates new instance of <c>XIncludingReader</c> class with + /// specified <c>Stream</c>. + /// </summary> + /// <param name="input"><c>Stream</c>.</param> + /// <param name="streamingMode">Work in streaming mode</param> + /// <remarks>Note: intra-document references are not supported in streaming mode.</remarks> + public XIncludingReader(Stream input, bool streamingMode) + : this(new XmlBaseAwareXmlTextReader(input), streamingMode) {} + + /// <summary> + /// Creates new instance of <c>XIncludingReader</c> class with + /// specified URL and <c>Stream</c>. + /// </summary> + /// <param name="input"><c>Stream</c>.</param> + /// <param name="url">Source document's URL</param> + /// <param name="streamingMode">Work in streaming mode</param> + /// <remarks>Note: intra-document references are not supported in streaming mode.</remarks> + public XIncludingReader(string url, Stream input, bool streamingMode) + : this(new XmlBaseAwareXmlTextReader(url, input), streamingMode) {} + + /// <summary> + /// Creates new instance of <c>XIncludingReader</c> class with + /// specified <c>Stream</c> and nametable. + /// </summary> + /// <param name="input"><c>Stream</c>.</param> + /// <param name="nt">Nametable</param> + /// <param name="streamingMode">Work in streaming mode</param> + /// <remarks>Note: intra-document references are not supported in streaming mode.</remarks> + public XIncludingReader(Stream input, XmlNameTable nt, bool streamingMode) : + this(new XmlBaseAwareXmlTextReader(input, nt), streamingMode) {} + + /// <summary> + /// Creates new instance of <c>XIncludingReader</c> class with + /// specified URL, <c>Stream</c> and nametable. + /// </summary> + /// <param name="input"><c>Stream</c>.</param> + /// <param name="nt">Nametable</param> + /// <param name="url">Source document's URL</param> + /// <param name="streamingMode">Work in streaming mode</param> + /// <remarks>Note: intra-document references are not supported in streaming mode.</remarks> + public XIncludingReader(string url, Stream input, XmlNameTable nt, bool streamingMode) : + this(new XmlBaseAwareXmlTextReader(url, input, nt), streamingMode) {} + + /// <summary> + /// Creates new instance of <c>XIncludingReader</c> class with + /// specified underlying <c>XmlReader</c> reader. + /// </summary> + /// <param name="reader">Underlying reader to read from.</param> + public XIncludingReader(XmlReader reader) + : this(reader, true) {} + + /// <summary> + /// Creates new instance of <c>XIncludingReader</c> class with + /// specified URL. + /// </summary> + /// <param name="url">Document location.</param> public XIncludingReader(string url) - : this(new XmlBaseAwareXmlTextReader(url)) {} + : this(new XmlBaseAwareXmlTextReader(url), true) {} /// <summary> /// Creates new instance of <c>XIncludingReader</c> class with @@ -112,7 +252,7 @@ /// <param name="url">Document location.</param> /// <param name="nt">Name table.</param> public XIncludingReader(string url, XmlNameTable nt) : - this(new XmlBaseAwareXmlTextReader(url, nt)) {} + this(new XmlBaseAwareXmlTextReader(url, nt), true) {} /// <summary> /// Creates new instance of <c>XIncludingReader</c> class with @@ -120,7 +260,7 @@ /// </summary> /// <param name="reader"><c>TextReader</c>.</param> public XIncludingReader(TextReader reader) - : this(new XmlBaseAwareXmlTextReader(reader)) {} + : this(new XmlBaseAwareXmlTextReader(reader), true) {} /// <summary> /// Creates new instance of <c>XIncludingReader</c> class with @@ -129,7 +269,7 @@ /// <param name="reader"><c>TextReader</c>.</param> /// <param name="url">Source document's URL</param> public XIncludingReader(string url, TextReader reader) - : this(new XmlBaseAwareXmlTextReader(url, reader)) {} + : this(new XmlBaseAwareXmlTextReader(url, reader), true) {} /// <summary> /// Creates new instance of <c>XIncludingReader</c> class with @@ -138,7 +278,7 @@ /// <param name="reader"><c>TextReader</c>.</param> /// <param name="nt">Nametable.</param> public XIncludingReader(TextReader reader, XmlNameTable nt) : - this(new XmlBaseAwareXmlTextReader(reader, nt)) {} + this(new XmlBaseAwareXmlTextReader(reader, nt), true) {} /// <summary> /// Creates new instance of <c>XIncludingReader</c> class with @@ -148,7 +288,7 @@ /// <param name="nt">Nametable.</param> /// <param name="url">Source document's URI</param> public XIncludingReader(string url, TextReader reader, XmlNameTable nt) : - this(new XmlBaseAwareXmlTextReader(url, reader, nt)) {} + this(new XmlBaseAwareXmlTextReader(url, reader, nt), true) {} /// <summary> /// Creates new instance of <c>XIncludingReader</c> class with @@ -156,7 +296,7 @@ /// </summary> /// <param name="input"><c>Stream</c>.</param> public XIncludingReader(Stream input) - : this(new XmlBaseAwareXmlTextReader(input)) {} + : this(new XmlBaseAwareXmlTextReader(input), true) {} /// <summary> /// Creates new instance of <c>XIncludingReader</c> class with @@ -165,7 +305,7 @@ /// <param name="input"><c>Stream</c>.</param> /// <param name="url">Source document's URL</param> public XIncludingReader(string url, Stream input) - : this(new XmlBaseAwareXmlTextReader(url, input)) {} + : this(new XmlBaseAwareXmlTextReader(url, input), true) {} /// <summary> /// Creates new instance of <c>XIncludingReader</c> class with @@ -174,7 +314,7 @@ /// <param name="input"><c>Stream</c>.</param> /// <param name="nt">Nametable</param> public XIncludingReader(Stream input, XmlNameTable nt) : - this(new XmlBaseAwareXmlTextReader(input, nt)) {} + this(new XmlBaseAwareXmlTextReader(input, nt), true) {} /// <summary> /// Creates new instance of <c>XIncludingReader</c> class with @@ -184,7 +324,7 @@ /// <param name="nt">Nametable</param> /// <param name="url">Source document's URL</param> public XIncludingReader(string url, Stream input, XmlNameTable nt) : - this(new XmlBaseAwareXmlTextReader(url, input, nt)) {} + this(new XmlBaseAwareXmlTextReader(url, input, nt), true) {} #endregion @@ -845,12 +985,19 @@ #endregion #region Public members + + /// <summary> + /// See <see cref="XmlTextReader.Normalization"/>. + /// </summary> public bool Normalization { get { return _normalization; } set { _normalization = value; } } + /// <summary> + /// See <see cref="XmlTextReader.WhitespaceHandling"/>. + /// </summary> public WhitespaceHandling WhitespaceHandling { get { return _whiteSpaceHandling; } @@ -885,6 +1032,14 @@ set { _exposeTextAsCDATA = value; } } + /// <summary> + /// Streaming or in-memory mode (streaming by default). + /// </summary> + public bool StreamingMode + { + get { return _streamingMode; } + } + #endregion @@ -1000,132 +1155,62 @@ { string href = _reader.GetAttribute(_keywords.Href); string xpointer = _reader.GetAttribute(_keywords.Xpointer); + string parse = _reader.GetAttribute(_keywords.Parse); + if (href == null || href == String.Empty) { - if (xpointer == null) - { - //Both href and xpointer attributes are absent, critical error - IXmlLineInfo li = _reader as IXmlLineInfo; - if (li != null && li.HasLineInfo()) - { - throw new MissingHrefAndXpointerException( - SR.GetString("MissingHrefAndXpointerExceptionLong", - _reader.BaseURI.ToString(), - li.LineNumber, li.LinePosition)); - } - else - throw new MissingHrefAndXpointerException( - SR.GetString("MissingHrefAndXpointerException", - _reader.BaseURI.ToString())); - } - else + //Intra-document inclusion + if (parse == null || parse.Equals(_keywords.Xml)) { - //No href - intra-document reference - throw new NotImplementedException(SR.IntradocumentReferencesNotSupported); - } - } - string parse = _reader.GetAttribute(_keywords.Parse); - if (parse == null || parse.Equals(_keywords.Xml)) - { - //Include document as XML - Uri includeLocation = ResolveHref(href); - if (includeLocation.Fragment != String.Empty) - throw new FragmentIdentifierInHrefAttribute(); - if (_xmlResolver == null) - { - //No custom resolver - WebResponse wRes; - Stream stream = GetResource(href, includeLocation, - _reader.GetAttribute(_keywords.Accept), - _reader.GetAttribute(_keywords.AcceptLanguage), out wRes); - //Push current reader to the stack - _readers.Push(_reader); - if (xpointer != null) + if (xpointer == null) { - //Well, XPointers should be resolved against the acquired infoset, - //not the source infoset - //TODO: Try to stream this stuff - string uri = wRes.ResponseUri.AbsoluteUri; - XIncludingReader xir = new XIncludingReader(uri, stream, _nameTable); - StringWriter sw = new StringWriter(); - XmlTextWriter w = new XmlTextWriter(sw); - while (xir.Read()) - w.WriteNode(xir, false); - xir.Close(); - w.Close(); - _reader = new XPointerReader(new XmlTextReader( - uri, new StringReader(sw.ToString())), xpointer); + //Both href and xpointer attributes are absent in xml mode, + // => critical error + IXmlLineInfo li = _reader as IXmlLineInfo; + if (li != null && li.HasLineInfo()) + { + throw new MissingHrefAndXpointerException( + SR.GetString("MissingHrefAndXpointerExceptionLong", + _reader.BaseURI.ToString(), + li.LineNumber, li.LinePosition)); + } + else + throw new MissingHrefAndXpointerException( + SR.GetString("MissingHrefAndXpointerException", + _reader.BaseURI.ToString())); } - else - { - _reader = new XmlBaseAwareXmlTextReader(wRes.ResponseUri.AbsoluteUri, stream, _nameTable); - ((XmlTextReader)_reader).Normalization = _normalization; - ((XmlTextReader)_reader).WhitespaceHandling = _whiteSpaceHandling; - } - bool res = Read(); - return res; - } - else + //No support for intra-document refs in streaming mode + if (_streamingMode) + throw new InvalidOperationException(SR.IntradocumentReferencesNotSupported); + return ProcessIntraDocXMLInclusion(xpointer); + } + else if (parse.Equals(_keywords.Text)) { - //Custom resolver provided, let's ask him - object resource; - try - { - resource = _xmlResolver.GetEntity(includeLocation, null, null); - } - catch (Exception e) - { - throw new ResourceException(SR.CustomXmlResolverError, e); - } - if (resource == null) - throw new ResourceException(SR.CustomXmlResolverReturnedNull); - //Ok, we accept Stream and XmlReader only - XmlReader r; - if (resource is Stream) - r = new XmlBaseAwareXmlTextReader(includeLocation.AbsoluteUri, (Stream)resource, _nameTable); - else if (resource is XmlReader) - r = (XmlReader)resource; - else - //Unsupported type - throw new ResourceException(SR.GetString( - "CustomXmlResolverReturnedUnsupportedType", - resource.GetType().ToString())); - //Push current reader to the stack - _readers.Push(_reader); - if (xpointer != null) - _reader = new XPointerReader(r, xpointer); - else - _reader = r; - bool res = Read(); - return res; + //No support for intra-document refs in streaming mode + if (_streamingMode) + throw new InvalidOperationException(SR.IntradocumentReferencesNotSupported); + return ProcessIntraDocTextInclusion(); } - } - else if (parse.Equals(_keywords.Text)) - { - //Include document as text - string encoding = GetAttribute(_keywords.Encoding); - Uri includeLocation = ResolveHref(href); - //Push current reader to the stack - _readers.Push(_reader); - _reader = new TextIncludingReader(includeLocation, encoding, - _reader.GetAttribute(_keywords.Accept), - _reader.GetAttribute(_keywords.AcceptLanguage), - _exposeTextAsCDATA); - return Read(); - } + } else { - //Unknown "parse" attribute value, critical error - IXmlLineInfo li = _reader as IXmlLineInfo; - if (li != null && li.HasLineInfo()) - { - throw new UnknownParseAttributeValueException(parse, - _reader.BaseURI.ToString(), - li.LineNumber, li.LinePosition); - } - else - throw new UnknownParseAttributeValueException(parse); - } + //Inter-document inclusion + if (parse == null || parse.Equals(_keywords.Xml)) + return ProcessInterDocXMLInclusion(href, xpointer); + else if (parse.Equals(_keywords.Text)) + return ProcessInterDocTextInclusion(href); + } + + //Unknown "parse" attribute value, critical error + IXmlLineInfo li2 = _reader as IXmlLineInfo; + if (li2 != null && li2.HasLineInfo()) + { + throw new UnknownParseAttributeValueException(parse, + _reader.BaseURI.ToString(), + li2.LineNumber, li2.LinePosition); + } + else + throw new UnknownParseAttributeValueException(parse); } /// <summary> @@ -1150,15 +1235,7 @@ catch (Exception e) { throw new ResourceException(SR.GetString("UnresolvableURI", href), e); - } - //Check circular inclusion - if (new Uri(_reader.BaseURI).Equals(includeLocation)) - ThrowCircularInclusionError(_reader, includeLocation); - foreach (XmlReader r in _readers) - { - if (new Uri(r.BaseURI).Equals(includeLocation)) - ThrowCircularInclusionError(_reader, includeLocation); - } + } return includeLocation; } @@ -1341,7 +1418,245 @@ return lang1 == lang2; } - #endregion - + /// <summary> + /// Creates a XmlReader over acquired infoset. + /// </summary> + /// <param name="uri">Resource URI</param> + /// <param name="stream">Stream to load from</param> + private XmlReader CreateAcquiredInfoset(string uri, Stream stream) + { + //TODO: Try to stream out this stuff + XIncludingReader xir = new XIncludingReader(uri, stream, _nameTable); + StringWriter sw = new StringWriter(); + XmlTextWriter w = new XmlTextWriter(sw); + while (xir.Read()) + w.WriteNode(xir, false); + xir.Close(); + w.Close(); + return new XmlTextReader(uri, new StringReader(sw.ToString())); + } + + /// <summary> + /// Creates a XmlReader over acquired infoset. + /// </summary> + /// <param name="reader">Source reader</param> + private XmlReader CreateAcquiredInfoset(XmlReader reader) + { + string uri = reader.BaseURI; + //TODO: Try to stream out this stuff + XIncludingReader xir = new XIncludingReader(reader); + StringWriter sw = new StringWriter(); + XmlTextWriter w = new XmlTextWriter(sw); + while (xir.Read()) + w.WriteNode(xir, false); + xir.Close(); + w.Close(); + return new XmlTextReader(uri, new StringReader(sw.ToString())); + } + + /// <summary> + /// Processes intra-document inclusion (no href attribute). + /// </summary> + /// <param name="xpointer">Required XPointer pointer</param> + private bool ProcessIntraDocXMLInclusion(string xpointer) + { + //TODO: So? + return false; + } + + /// <summary> + /// Processes inter-document inclusion (xml mode). + /// </summary> + /// <param name="href">'href' attr value</param> + /// <param name="xpointer">'xpointer attr value'</param> + private bool ProcessInterDocXMLInclusion(string href, string xpointer) + { + //Include document as XML + Uri includeLocation = ResolveHref(href); + CheckLoops(includeLocation); + if (includeLocation.Fragment != String.Empty) + throw new FragmentIdentifierInHrefAttribute(); + if (_xmlResolver == null) + { + //No custom resolver + WebResponse wRes; + Stream stream = GetResource(href, includeLocation, + _reader.GetAttribute(_keywords.Accept), + _reader.GetAttribute(_keywords.AcceptLanguage), out wRes); + //Push current reader to the stack + _readers.Push(_reader); + if (xpointer != null) + { + //XPointers should be resolved against the acquired infoset, + //not the source infoset + _reader = new XPointerReader( + CreateAcquiredInfoset(wRes.ResponseUri.AbsoluteUri, stream), xpointer); + } + else + { + XmlTextReader r = new XmlBaseAwareXmlTextReader(wRes.ResponseUri.AbsoluteUri, stream, _nameTable); + r.Normalization = _normalization; + r.WhitespaceHandling = _whiteSpaceHandling; + if (_streamingMode) + _reader = r; + else + _reader = CreateInMemoryReader(r); + } + bool res = Read(); + return res; + } + else + { + //Custom resolver provided, let's ask him + object resource; + try + { + resource = _xmlResolver.GetEntity(includeLocation, null, null); + } + catch (Exception e) + { + throw new ResourceException(SR.CustomXmlResolverError, e); + } + if (resource == null) + throw new ResourceException(SR.CustomXmlResolverReturnedNull); + + //Push current reader to the stack + _readers.Push(_reader); + + //Ok, we accept Stream and XmlReader only + if (xpointer != null) + { + if (resource is Stream) + { + //XPointers should be resolved against the acquired infoset, + //not the source infoset + _reader = new XPointerReader( + CreateAcquiredInfoset(includeLocation.AbsoluteUri, (Stream)resource), + xpointer); + } + else if (resource is XmlReader) + { + _reader = new XPointerReader( + CreateAcquiredInfoset((XmlReader)resource), xpointer); + } + else + { + //Unsupported type + throw new ResourceException(SR.GetString( + "CustomXmlResolverReturnedUnsupportedType", + resource.GetType().ToString())); + } + } + else + { + //No XPointer + if (resource is Stream) + { + XmlTextReader r = new XmlBaseAwareXmlTextReader(includeLocation.AbsoluteUri, (Stream)resource, _nameTable); + if (_streamingMode) + _reader = r; + else + _reader = CreateInMemoryReader(r); + } + else if (resource is XmlReader) + { + if (_streamingMode) + _reader = (XmlReader)resource; + else + _reader = CreateInMemoryReader((XmlReader)resource); + } + else + { + //Unsupported type + throw new ResourceException(SR.GetString( + "CustomXmlResolverReturnedUnsupportedType", + resource.GetType().ToString())); + } + } + + return Read(); + } + } + + /// <summary> + /// Process inter-document inclusion as text. + /// </summary> + /// <param name="href">'href' attr value</param> + private bool ProcessInterDocTextInclusion(string href) + { + //Include document as text + string encoding = GetAttribute(_keywords.Encoding); + Uri includeLocation = ResolveHref(href); + //No need to check loops when including as text + //Push current reader to the stack + _readers.Push(_reader); + _reader = new TextIncludingReader(includeLocation, encoding, + _reader.GetAttribute(_keywords.Accept), + _reader.GetAttribute(_keywords.AcceptLanguage), + _exposeTextAsCDATA); + return Read(); + } + + /// <summary> + /// Process intra-document inclusion as text. + /// </summary> + private bool ProcessIntraDocTextInclusion() + { + //Ok, in non-streaming mode _reader must implement IHasXPathNavigator + if (_reader is IHasXPathNavigator) + { + XPathNavigator nav = ((IHasXPathNavigator)_reader).GetNavigator(); + nav.MoveToRoot(); + XPathNavigatorReader r= new XPathNavigatorReader(nav); + r.Read(); + //Push current reader to the stack + _readers.Push(_reader); + _reader = new TextIncludingReader(r.ReadOuterXml(), _exposeTextAsCDATA); + r.Close(); + return Read(); + } + else + throw new InvalidOperationException("How this could happen?"); + } + + /// <summary> + /// Creates XmlReader for non-streaming mode. + /// </summary> + /// <param name="reader">Source reader</param> + private XmlReader CreateInMemoryReader(XmlReader reader) + { + XmlReader r = null; + if (reader is XmlTextReader) + { + XmlValidatingReader vr = new XmlValidatingReader(reader); + vr.ValidationType = ValidationType.None; + vr.EntityHandling = EntityHandling.ExpandEntities; + vr.ValidationEventHandler += new ValidationEventHandler( + ValidationCallback); + r = vr; + } + else + r = reader; + XPathDocument doc = new XPathDocument(r, XmlSpace.Preserve); + return new XPathNavigatorReader(doc.CreateNavigator()); + } + + /// <summary> + /// Checks for inclusion loops. + /// </summary> + /// <param name="url"></param> + private void CheckLoops(Uri url) + { + //Check circular inclusion + if (new Uri(_reader.BaseURI).Equals(url)) + ThrowCircularInclusionError(_reader, url); + foreach (XmlReader r in _readers) + { + if (new Uri(r.BaseURI).Equals(url)) + ThrowCircularInclusionError(_reader, url); + } + } + + #endregion } } Index: SR.resx =================================================================== RCS file: /cvsroot/mvp-xml/XInclude/v1/src/SR.resx,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- SR.resx 26 Oct 2004 19:28:41 -0000 1.4 +++ SR.resx 28 Oct 2004 18:27:05 -0000 1.5 @@ -91,7 +91,7 @@ <value>'href' or 'xpointer' attributes can't both be omitted on xi:include element. Location: {0}, Line {1}, Position {2}.</value> </data> <data name="IntradocumentReferencesNotSupported" type="System.String" mimetype="System.String"> - <value>Intra-document references are not supported yet.</value> + <value>Intra-document references are not supported in the streaming mode.</value> </data> <data name="CustomXmlResolverError" type="System.String" mimetype="System.String"> <value>An exception has occured during GetEntity call to custom XmlResolver.</value> Index: TextIncludingReader.cs =================================================================== RCS file: /cvsroot/mvp-xml/XInclude/v1/src/TextIncludingReader.cs,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- TextIncludingReader.cs 26 Oct 2004 19:28:41 -0000 1.5 +++ TextIncludingReader.cs 28 Oct 2004 18:27:05 -0000 1.6 @@ -45,6 +45,13 @@ _exposeCDATA = exposeCDATA; } + public TextIncludingReader(string value, bool exposeCDATA) + { + _state = ReadState.Initial; + _exposeCDATA = exposeCDATA; + _value = value; + } + #endregion #region XmlReader overrides @@ -197,57 +204,72 @@ public override void ResolveEntity() {} public override bool Read() { - switch (_state) { + switch (_state) { case ReadState.Initial: - WebResponse wRes; - Stream stream = XIncludingReader.GetResource(_includeLocation.AbsoluteUri, - _includeLocation, _accept, _acceptLanguage, out wRes); - StreamReader reader; - /* According to the spec, encoding should be determined as follows: - * external encoding information, if available, otherwise - * if the media type of the resource is text/xml, application/xml, - or matches the conventions text/*+xml or application/*+xml as - described in XML Media Types [IETF RFC 3023], the encoding is - recognized as specified in XML 1.0, otherwise - * the value of the encoding attribute if one exists, otherwise - * UTF-8. - */ - try { - //TODO: try to get "content-encoding" from wRes.Headers collection? - //If mime type is xml-aware, get resource encoding as per XML 1.0 - string contentType = wRes.ContentType.ToLower(); - if (contentType == "text/xml" || - contentType == "application/xml" || - contentType.StartsWith("text/") && contentType.EndsWith("+xml") || - contentType.StartsWith("application/") && contentType.EndsWith("+xml")) { - //Yes, that's xml, let's read encoding from the xml declaration - reader = new StreamReader(stream, GetEncodingFromXMLDecl(_href)); - } else if (_encoding != null) { - //Try to use user-specified encoding - Encoding enc; - try { - enc = Encoding.GetEncoding(_encoding); - } - catch (Exception e) { - throw new ResourceException(SR.GetString("NotSupportedEncoding", - _encoding), e); - } - reader = new StreamReader(stream, enc); - } - else - //Fallback to UTF-8 - reader = new StreamReader(stream, Encoding.UTF8); - _value = reader.ReadToEnd(); - TextUtils.CheckForNonXmlChars(_value); - } catch (ResourceException re) { - throw re; - } catch (OutOfMemoryException oome) { - //Crazy include - memory is out - //TODO: what about reading by chunks? - throw new ResourceException(SR.GetString("OutOfMemoryWhileFetchingResource", _href), oome); - } catch (IOException ioe) { - throw new ResourceException(SR.GetString("IOErrorWhileFetchingResource", _href), ioe); - } + if (_value == null) + { + WebResponse wRes; + Stream stream = XIncludingReader.GetResource(_includeLocation.AbsoluteUri, + _includeLocation, _accept, _acceptLanguage, out wRes); + StreamReader reader; + /* According to the spec, encoding should be determined as follows: + * external encoding information, if available, otherwise + * if the media type of the resource is text/xml, application/xml, + or matches the conventions text/*+xml or application/*+xml as + described in XML Media Types [IETF RFC 3023], the encoding is + recognized as specified in XML 1.0, otherwise + * the value of the encoding attribute if one exists, otherwise + * UTF-8. + */ + try + { + //TODO: try to get "content-encoding" from wRes.Headers collection? + //If mime type is xml-aware, get resource encoding as per XML 1.0 + string contentType = wRes.ContentType.ToLower(); + if (contentType == "text/xml" || + contentType == "application/xml" || + contentType.StartsWith("text/") && contentType.EndsWith("+xml") || + contentType.StartsWith("application/") && contentType.EndsWith("+xml")) + { + //Yes, that's xml, let's read encoding from the xml declaration + reader = new StreamReader(stream, GetEncodingFromXMLDecl(_href)); + } + else if (_encoding != null) + { + //Try to use user-specified encoding + Encoding enc; + try + { + enc = Encoding.GetEncoding(_encoding); + } + catch (Exception e) + { + throw new ResourceException(SR.GetString("NotSupportedEncoding", + _encoding), e); + } + reader = new StreamReader(stream, enc); + } + else + //Fallback to UTF-8 + reader = new StreamReader(stream, Encoding.UTF8); + _value = reader.ReadToEnd(); + TextUtils.CheckForNonXmlChars(_value); + } + catch (ResourceException re) + { + throw re; + } + catch (OutOfMemoryException oome) + { + //Crazy include - memory is out + //TODO: what about reading by chunks? + throw new ResourceException(SR.GetString("OutOfMemoryWhileFetchingResource", _href), oome); + } + catch (IOException ioe) + { + throw new ResourceException(SR.GetString("IOErrorWhileFetchingResource", _href), ioe); + } + } _state = ReadState.Interactive; return true; case ReadState.Interactive: |