//
// (C)2003 Atsushi Enomoto
//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
using System;
using System.Collections;
-//using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Schema;
+#if NET_2_0
+using System.Collections.Generic;
+#endif
+#if NET_2_1
+using XmlSchemaException = System.Xml.XmlException;
+#else
using Mono.Xml.Schema;
-using Mono.Xml.Native;
+#endif
+
+#if NET_2_0
+using XmlTextReaderImpl = Mono.Xml2.XmlTextReader;
+#else
+using XmlTextReaderImpl = System.Xml.XmlTextReader;
+#endif
namespace Mono.Xml
{
get { return linePosition; }
set { linePosition = value; }
}
-
+
+#if !NET_2_1
+ internal XmlSchema CreateXsdSchema ()
+ {
+ XmlSchema s = new XmlSchema ();
+ s.SourceUri = BaseURI;
+ s.LineNumber = LineNumber;
+ s.LinePosition = LinePosition;
+ foreach (DTDElementDeclaration el in ElementDecls.Values)
+ s.Items.Add (el.CreateXsdElement ());
+ return s;
+ }
+#endif
+
public string ResolveEntity (string name)
{
DTDEntityDeclaration decl = EntityDecls [name]
as DTDEntityDeclaration;
if (decl == null) {
+#if NET_2_1
+ AddError (new XmlSchemaException (String.Format ("Required entity was not found: {0}", name), null, this.LineNumber, this.LinePosition));
+#else
AddError (new XmlSchemaException ("Required entity was not found.",
this.LineNumber, this.LinePosition, null, this.BaseURI, null));
+#endif
return " ";
}
else
{
validationErrors.Add (ex);
}
+
+ internal string GenerateEntityAttributeText (string entityName)
+ {
+ DTDEntityDeclaration entity = EntityDecls [entityName] as DTDEntityDeclaration;
+ if (entity == null)
+ return null;
+ return entity.EntityValue;
+ }
+
+ internal XmlTextReaderImpl GenerateEntityContentReader (string entityName, XmlParserContext context)
+ {
+ DTDEntityDeclaration entity = EntityDecls [entityName] as DTDEntityDeclaration;
+ if (entity == null)
+ return null;
+
+ if (entity.SystemId != null) {
+ Uri baseUri = entity.BaseURI == String.Empty ? null : new Uri (entity.BaseURI);
+ Stream stream = resolver.GetEntity (resolver.ResolveUri (baseUri, entity.SystemId), null, typeof (Stream)) as Stream;
+ return new XmlTextReaderImpl (stream, XmlNodeType.Element, context);
+ }
+ else
+ return new XmlTextReaderImpl (entity.EntityValue, XmlNodeType.Element, context);
+ }
}
+#if NET_2_0
+ class DictionaryBase : List<KeyValuePair<string,DTDNode>>
+ {
+ public IEnumerable<DTDNode> Values {
+ get {
+ foreach (KeyValuePair<string,DTDNode> p in this)
+ yield return p.Value;
+ }
+ }
+ }
+#endif
internal class DTDCollectionBase : DictionaryBase
{
DTDObjectModel root;
get { return root; }
}
+#if NET_2_0
+ public DictionaryBase InnerHashtable {
+ get { return this; }
+ }
+
+ protected void BaseAdd (string name, DTDNode value)
+ {
+ base.Add (new KeyValuePair<string,DTDNode> (name, value));
+ }
+
+ public bool Contains (string key)
+ {
+ foreach (KeyValuePair<string,DTDNode> p in this)
+ if (p.Key == key)
+ return true;
+ return false;
+ }
+
+ protected object BaseGet (string name)
+ {
+ foreach (KeyValuePair<string,DTDNode> p in this)
+ if (p.Key == name)
+ return p.Value;
+ return null;
+ }
+#else
public ICollection Keys {
get { return InnerHashtable.Keys; }
}
public ICollection Values {
get { return InnerHashtable.Values; }
}
+
+ protected void BaseAdd (string name, object value)
+ {
+ InnerHashtable.Add (name, value);
+ }
+
+ public bool Contains (string key)
+ {
+ return InnerHashtable.Contains (key);
+ }
+
+ protected object BaseGet (string name)
+ {
+ return InnerHashtable [name];
+ }
+#endif
}
internal class DTDElementDeclarationCollection : DTDCollectionBase
public DTDElementDeclaration Get (string name)
{
- return InnerHashtable [name] as DTDElementDeclaration;
+ return BaseGet (name) as DTDElementDeclaration;
}
public void Add (string name, DTDElementDeclaration decl)
{
- if (InnerHashtable.Contains (name)) {
+ if (Contains (name)) {
Root.AddError (new XmlSchemaException (String.Format (
"Element declaration for {0} was already added.",
name), null));
return;
}
decl.SetRoot (Root);
- InnerHashtable.Add (name, decl);
+ BaseAdd (name, decl);
}
}
public DTDAttListDeclarationCollection (DTDObjectModel root) : base (root) {}
public DTDAttListDeclaration this [string name] {
- get { return InnerHashtable [name] as DTDAttListDeclaration; }
+ get { return BaseGet (name) as DTDAttListDeclaration; }
}
public void Add (string name, DTDAttListDeclaration decl)
existing.Add (def);
} else {
decl.SetRoot (Root);
- InnerHashtable.Add (name, decl);
+ BaseAdd (name, decl);
}
}
}
public DTDEntityDeclarationCollection (DTDObjectModel root) : base (root) {}
public DTDEntityDeclaration this [string name] {
- get { return InnerHashtable [name] as DTDEntityDeclaration; }
+ get { return BaseGet (name) as DTDEntityDeclaration; }
}
public void Add (string name, DTDEntityDeclaration decl)
{
- if (InnerHashtable [name] != null)
+ if (Contains (name))
throw new InvalidOperationException (String.Format (
"Entity declaration for {0} was already added.",
name));
decl.SetRoot (Root);
- InnerHashtable.Add (name, decl);
+ BaseAdd (name, decl);
}
}
public DTDNotationDeclarationCollection (DTDObjectModel root) : base (root) {}
public DTDNotationDeclaration this [string name] {
- get { return InnerHashtable [name] as DTDNotationDeclaration; }
+ get { return BaseGet (name) as DTDNotationDeclaration; }
}
public void Add (string name, DTDNotationDeclaration decl)
{
- if (InnerHashtable [name] != null)
+ if (Contains (name))
throw new InvalidOperationException (String.Format (
"Notation declaration for {0} was already added.",
name));
decl.SetRoot (Root);
- InnerHashtable.Add (name, decl);
+ BaseAdd (name, decl);
}
}
return compiledAutomata;
}
+#if !NET_2_1
+ internal XmlSchemaParticle CreateXsdParticle ()
+ {
+ XmlSchemaParticle p = CreateXsdParticleCore ();
+ if (p == null)
+ return null;
+
+ switch (Occurence) {
+ case DTDOccurence.Optional:
+ p.MinOccurs = 0;
+ break;
+ case DTDOccurence.OneOrMore:
+ p.MaxOccursString = "unbounded";
+ break;
+ case DTDOccurence.ZeroOrMore:
+ p.MinOccurs = 0;
+ p.MaxOccursString = "unbounded";
+ break;
+ }
+ return p;
+ }
+
+ XmlSchemaParticle CreateXsdParticleCore ()
+ {
+ XmlSchemaParticle p = null;
+ if (ElementName != null) {
+ XmlSchemaElement el = new XmlSchemaElement ();
+ SetLineInfo (el);
+ el.RefName = new XmlQualifiedName (ElementName);
+ return el;
+ }
+ else if (ChildModels.Count == 0)
+ return null;
+ else {
+ XmlSchemaGroupBase gb =
+ (OrderType == DTDContentOrderType.Seq) ?
+ (XmlSchemaGroupBase)
+ new XmlSchemaSequence () :
+ new XmlSchemaChoice ();
+ SetLineInfo (gb);
+ foreach (DTDContentModel cm in ChildModels.Items) {
+ XmlSchemaParticle c = cm.CreateXsdParticle ();
+ if (c != null)
+ gb.Items.Add (c);
+ }
+ p = gb;
+ }
+ return p;
+ }
+#endif
+
private DTDAutomata CompileInternal ()
{
if (ElementDecl.IsAny)
{
return l.MakeChoice (r);
}
-
}
internal class DTDContentModelCollection
{
}
+ public IList Items {
+ get { return contentModel; }
+ }
+
public DTDContentModel this [int i] {
get { return contentModel [i] as DTDContentModel; }
}
protected DTDObjectModel Root {
get { return root; }
}
+
+ internal XmlException NotWFError (string message)
+ {
+ return new XmlException (this as IXmlLineInfo, BaseURI, message);
+ }
+
+#if !NET_2_1
+ public void SetLineInfo (XmlSchemaObject obj)
+ {
+ obj.SourceUri = BaseURI;
+ obj.LineNumber = LineNumber;
+ obj.LinePosition = LinePosition;
+ }
+#endif
}
internal class DTDElementDeclaration : DTDNode
return Root.AttListDecls [Name];
}
}
+
+#if !NET_2_1
+ internal XmlSchemaElement CreateXsdElement ()
+ {
+ XmlSchemaElement el = new XmlSchemaElement ();
+ SetLineInfo (el);
+ el.Name = Name;
+
+ XmlSchemaComplexType ct = new XmlSchemaComplexType ();
+ el.SchemaType = ct;
+ if (Attributes != null) {
+ SetLineInfo (ct);
+ foreach (DTDAttributeDefinition a in
+ Attributes.Definitions)
+ ct.Attributes.Add (a.CreateXsdAttribute ());
+ }
+ if (IsEmpty)
+ ; // nothing to do
+ else if (IsAny) {
+ XmlSchemaAny any = new XmlSchemaAny ();
+ any.MinOccurs = 0;
+ any.MaxOccursString = "unbounded";
+ ct.Particle = any;
+ }
+ else {
+ if (IsMixedContent)
+ ct.IsMixed = true;
+ ct.Particle = ContentModel.CreateXsdParticle ();
+ }
+
+ /*
+ if (IsEmpty) {
+ el.SchemaType = new XmlSchemaComplexType ();
+ SetLineInfo (el.SchemaType);
+ }
+ else if (IsAny)
+ el.SchemaTypeName = new XmlQualifiedName (
+ "anyType", XmlSchema.Namespace);
+ else {
+ XmlSchemaComplexType ct = new XmlSchemaComplexType ();
+ SetLineInfo (ct);
+ if (Attributes != null)
+ foreach (DTDAttributeDefinition a in
+ Attributes.Definitions)
+ ct.Attributes.Add (a.CreateXsdAttribute ());
+ if (IsMixedContent)
+ ct.IsMixed = true;
+ ct.Particle = ContentModel.CreateXsdParticle ();
+ el.SchemaType = ct;
+ }
+ */
+ return el;
+ }
+#endif
}
internal class DTDAttributeDefinition : DTDNode
resolvedNormalizedDefaultValue =
(o is string []) ?
String.Join (" ", (string []) o) :
- o.ToString ();
+ o is IFormattable ? ((IFormattable) o).ToString (null, CultureInfo.InvariantCulture) : o.ToString ();
} catch (Exception) {
// This is for non-error-reporting reader
resolvedNormalizedDefaultValue = Datatype.Normalize (s);
}
}
+#if !NET_2_1
+ internal XmlSchemaAttribute CreateXsdAttribute ()
+ {
+ XmlSchemaAttribute a = new XmlSchemaAttribute ();
+ SetLineInfo (a);
+ a.Name = Name;
+ a.DefaultValue = resolvedNormalizedDefaultValue;
+ if (OccurenceType != DTDAttributeOccurenceType.Required)
+ a.Use = XmlSchemaUse.Optional;
+
+ XmlQualifiedName qname = XmlQualifiedName.Empty;
+ ArrayList enumeration = null;
+ if (enumeratedNotations != null && enumeratedNotations.Count > 0) {
+ qname = new XmlQualifiedName ("NOTATION", XmlSchema.Namespace);
+ enumeration = enumeratedNotations;
+ }
+ else if (enumeratedLiterals != null)
+ enumeration = enumeratedLiterals;
+ else {
+ switch (Datatype.TokenizedType) {
+ case XmlTokenizedType.ID:
+ qname = new XmlQualifiedName ("ID", XmlSchema.Namespace); break;
+ case XmlTokenizedType.IDREF:
+ qname = new XmlQualifiedName ("IDREF", XmlSchema.Namespace); break;
+ case XmlTokenizedType.IDREFS:
+ qname = new XmlQualifiedName ("IDREFS", XmlSchema.Namespace); break;
+ case XmlTokenizedType.ENTITY:
+ qname = new XmlQualifiedName ("ENTITY", XmlSchema.Namespace); break;
+ case XmlTokenizedType.ENTITIES:
+ qname = new XmlQualifiedName ("ENTITIES", XmlSchema.Namespace); break;
+ case XmlTokenizedType.NMTOKEN:
+ qname = new XmlQualifiedName ("NMTOKEN", XmlSchema.Namespace); break;
+ case XmlTokenizedType.NMTOKENS:
+ qname = new XmlQualifiedName ("NMTOKENS", XmlSchema.Namespace); break;
+ case XmlTokenizedType.NOTATION:
+ qname = new XmlQualifiedName ("NOTATION", XmlSchema.Namespace); break;
+ }
+ }
+
+ if (enumeration != null) {
+ XmlSchemaSimpleType st = new XmlSchemaSimpleType ();
+ SetLineInfo (st);
+ XmlSchemaSimpleTypeRestriction r =
+ new XmlSchemaSimpleTypeRestriction ();
+ SetLineInfo (r);
+ r.BaseTypeName = qname;
+ if (enumeratedNotations != null) {
+ foreach (string name in enumeratedNotations) {
+ XmlSchemaEnumerationFacet f =
+ new XmlSchemaEnumerationFacet ();
+ SetLineInfo (f);
+ r.Facets.Add (f);
+ f.Value = name;
+ }
+ }
+ st.Content = r;
+ }
+ else if (qname != XmlQualifiedName.Empty)
+ a.SchemaTypeName = qname;
+ return a;
+ }
+#endif
+
internal string ComputeDefaultValue ()
{
if (UnresolvedDefaultValue == null)
}
else
spec = value.Substring (next + 2, semicolon - next - 2);
- sb.Append ((char) int.Parse (spec, style));
+ sb.Append ((char) int.Parse (spec, style, CultureInfo.InvariantCulture));
} else {
sb.Append (value.Substring (pos, next - 1));
string name = value.Substring (next + 1, semicolon - 2);
string systemId;
string literalValue;
string replacementText;
+ string uriString;
+ Uri absUri;
bool isInvalid;
- Exception loadException;
+// Exception loadException;
bool loadFailed;
+ XmlResolver resolver;
protected DTDEntityBase (DTDObjectModel root)
{
set { replacementText = value; }
}
- public void Resolve (XmlResolver resolver)
+ public XmlResolver XmlResolver {
+ set { resolver = value; }
+ }
+
+ public string ActualUri {
+ get {
+ if (uriString == null) {
+ if (resolver == null || SystemId == null || SystemId.Length == 0)
+ uriString = BaseURI;
+ else {
+ Uri baseUri = null;
+ try {
+ if (BaseURI != null && BaseURI.Length > 0)
+ baseUri = new Uri (BaseURI);
+ } catch (UriFormatException) {
+ }
+
+ absUri = resolver.ResolveUri (baseUri, SystemId);
+ uriString = absUri != null ? absUri.ToString () : String.Empty;
+ }
+ }
+ return uriString;
+ }
+ }
+
+ public void Resolve ()
{
- if (resolver == null || SystemId == null || SystemId.Length == 0) {
+ if (ActualUri == String.Empty) {
LoadFailed = true;
LiteralEntityValue = String.Empty;
return;
}
- Uri baseUri = null;
- try {
- if (BaseURI != null && BaseURI.Length > 0)
- baseUri = new Uri (BaseURI);
- } catch (UriFormatException) {
- }
-
- Uri absUri = resolver.ResolveUri (baseUri, SystemId);
- string absPath = absUri.ToString ();
- if (Root.ExternalResources.ContainsKey (absPath))
- LiteralEntityValue = (string) Root.ExternalResources [absPath];
+ if (Root.ExternalResources.ContainsKey (ActualUri))
+ LiteralEntityValue = (string) Root.ExternalResources [ActualUri];
+ Stream s = null;
try {
- Stream s = resolver.GetEntity (absUri, null, typeof (Stream)) as Stream;
- XmlTextReader xtr = new XmlTextReader (s);
+ s = resolver.GetEntity (absUri, null, typeof (Stream)) as Stream;
+ XmlTextReaderImpl xtr = new XmlTextReaderImpl (ActualUri, s, Root.NameTable);
// Don't skip Text declaration here. LiteralEntityValue contains it. See spec 4.5
- this.BaseURI = absPath;
LiteralEntityValue = xtr.GetRemainder ().ReadToEnd ();
- Root.ExternalResources.Add (absPath, LiteralEntityValue);
+ Root.ExternalResources.Add (ActualUri, LiteralEntityValue);
if (Root.ExternalResources.Count > DTDObjectModel.AllowedExternalEntitiesMax)
throw new InvalidOperationException ("The total amount of external entities exceeded the allowed number.");
- } catch (Exception ex) {
- loadException = ex;
+ } catch (Exception) {
+// loadException = ex;
LiteralEntityValue = String.Empty;
LoadFailed = true;
-// throw new XmlException (this, "Cannot resolve external entity. URI is " + absPath + " .");
+// throw NotWFError ("Cannot resolve external entity. URI is " + ActualUri + " .");
+ } finally {
+ if (s != null)
+ s.Close ();
}
}
}
hasExternalReference = true;
if (recursed)
- throw new XmlException ("Entity recursion was found.");
+ throw NotWFError ("Entity recursion was found.");
recursed = true;
if (scanned) {
foreach (string referenced in refs)
if (this.ReferencingEntities.Contains (referenced))
- throw new XmlException (String.Format (
+ throw NotWFError (String.Format (
"Nested entity was found between {0} and {1}",
referenced, Name));
recursed = false;
break;
string name = value.Substring (start, i - start);
if (name.Length == 0)
- throw new XmlException (this as IXmlLineInfo, "Entity reference name is missing.");
+ throw NotWFError ("Entity reference name is missing.");
if (name [0] == '#')
break; // character reference
if (XmlChar.GetPredefinedEntity (name) >= 0)
}
}
if (start != 0)
+#if NET_2_1
+ Root.AddError (new XmlSchemaException (this, this.BaseURI, "Invalid reference character '&' is specified."));
+#else
Root.AddError (new XmlSchemaException ("Invalid reference character '&' is specified.",
this.LineNumber, this.LinePosition, null, this.BaseURI, null));
+#endif
scanned = true;
recursed = false;
}
}
}
- public enum DTDContentOrderType
+ internal enum DTDContentOrderType
{
None,
Seq,
Or
}
- public enum DTDAttributeOccurenceType
+ internal enum DTDAttributeOccurenceType
{
None,
Required,
Fixed
}
- public enum DTDOccurence
+ internal enum DTDOccurence
{
One,
Optional,