using System;
using System.Xml;
using System.Collections;
using Mono.Xml;
using Mono.Xml.Schema;
using System.Xml.Serialization;
namespace System.Xml.Schema
{
///
/// All Methods in this class should use XmlConvert. Some Methods are not present in the
/// MS Implementation. We should provide them.
///
internal class XmlSchemaUtil
{
static XmlSchemaUtil()
{
FinalAllowed = XmlSchemaDerivationMethod.Restriction |
XmlSchemaDerivationMethod.Extension;
ComplexTypeBlockAllowed = FinalAllowed;
ElementBlockAllowed = XmlSchemaDerivationMethod.Substitution |
FinalAllowed;
}
internal static XmlSchemaDerivationMethod FinalAllowed;
internal static XmlSchemaDerivationMethod ElementBlockAllowed;
internal static XmlSchemaDerivationMethod ComplexTypeBlockAllowed;
public static void AddToTable (XmlSchemaObjectTable table, XmlSchemaObject obj,
XmlQualifiedName qname, ValidationEventHandler h)
{
if (table.Contains (qname)) {
// FIXME: This logic unexpectedly allows
// one redefining item and two or more redefining items.
// FIXME: redefining item is not simple replacement,
// but much more complex stuff.
if (obj.isRedefineChild) { // take precedence.
if (obj.redefinedObject != null)
obj.error (h, "Named item " + qname + " was already contained in the schema object table.");
else
obj.redefinedObject = table [qname];
table.Set (qname, obj);
}
else if (table [qname].isRedefineChild) {
if (table [qname].redefinedObject != null)
obj.error (h, "Named item " + qname + " was already contained in the schema object table.");
else
table [qname].redefinedObject = obj;
return; // never add to the table.
}
else
obj.error (h, "Named item " + qname + " was already contained in the schema object table.");
}
else
table.Set (qname, obj);
}
public static void CompileID(string id, XmlSchemaObject xso, Hashtable idCollection, ValidationEventHandler h)
{
//check if the string conforms to http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/datatypes.html#ID
// 1. ID must be a NCName
// 2. ID must be unique in the schema
if(id == null)
return;
if(!CheckNCName(id))
xso.error(h,id+" is not a valid id attribute");
else if(idCollection.ContainsKey(id))
xso.error(h,"Duplicate id attribute "+id);
else
idCollection.Add(id,xso);
}
[MonoTODO]
public static bool CheckAnyUri(string uri)
{
if (uri.StartsWith ("##"))
return false;
return true;
}
public static bool CheckToken(string token)
{
//check if the string conforms to http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/datatypes.html#token
return true;
}
public static bool CheckNormalizedString(string token)
{
return true;
}
public static bool CheckLanguage(string lang)
{
//check if the string conforms to http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/datatypes.html#language
return true;
}
public static bool CheckNCName(string name)
{
//check if the string conforms to http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/datatypes.html#NCName
try
{
XmlConvert.VerifyNCName(name);
return true;
}
catch(Exception ex)
{
return false;
}
}
public static bool CheckQName(XmlQualifiedName qname)
{
// What is this doing?
return true;
}
public static XmlParserContext GetParserContext (XmlReader reader)
{
XmlTextReader xtr = reader as XmlTextReader;
if (xtr != null)
return xtr.GetInternalParserContext ();
XmlNodeReader xnr = reader as XmlNodeReader;
if (xnr != null)
return xnr.GetInternalParserContext ();
XmlValidatingReader xvr = reader as XmlValidatingReader;
if (xvr != null)
return xvr.GetInternalParserContext ();
IHasXmlParserContext xctx = reader as IHasXmlParserContext;
if (xctx != null)
return xctx.ParserContext;
throw new NotSupportedException ("XmlParserContext cannot be acquired from this XmlReader.");
}
public static bool IsSchemaDatatypeEquals (XsdAnySimpleType st1, object v1,
XsdAnySimpleType st2, object v2)
{
if (v1 == null || v2 == null)
return false;
if (st1 == null)
st1 = XmlSchemaSimpleType.AnySimpleType;
if (st2 == null)
st2 = XmlSchemaSimpleType.AnySimpleType;
Type t = st2.GetType ();
if (st1 is XsdFloat) {
return st2 is XsdFloat && Convert.ToSingle (v1) == Convert.ToSingle (v2);
} else if (st1 is XsdDouble) {
return st2 is XsdDouble && Convert.ToDouble (v1) == Convert.ToDouble (v2);
} else if (st1 is XsdDecimal) {
if (!(st2 is XsdDecimal) || Convert.ToDecimal (v1) != Convert.ToDecimal (v2))
return false;
if (st1 is XsdNonPositiveInteger)
return st2 is XsdNonPositiveInteger || t == typeof (XsdDecimal) || t == typeof (XsdInteger);
else if (st1 is XsdPositiveInteger)
return st2 is XsdPositiveInteger || t == typeof (XsdDecimal) ||
t == typeof (XsdInteger) || t == typeof (XsdNonNegativeInteger);
else if (st1 is XsdUnsignedLong)
return st2 is XsdUnsignedLong || t == typeof (XsdDecimal) ||
t == typeof (XsdInteger) || t == typeof (XsdNonNegativeInteger);
else if (st1 is XsdNonNegativeInteger)
return st2 is XsdNonNegativeInteger || t == typeof (XsdDecimal) || t == typeof (XsdInteger);
else if (st1 is XsdLong)
return st2 is XsdLong || t == typeof (XsdDecimal) || t == typeof (XsdInteger);
return true;
}
else if (!v1.Equals (v2))
return false;
if (st1 is XsdString) {
if (!(st2 is XsdString))
return false;
if (st1 is XsdNMToken && (st2 is XsdLanguage || st2 is XsdName))
return false;
if (st2 is XsdNMToken && (st1 is XsdLanguage || st1 is XsdName))
return false;
if (st1 is XsdName && (st2 is XsdLanguage || st2 is XsdNMToken))
return false;
if (st2 is XsdName && (st1 is XsdLanguage || st1 is XsdNMToken))
return false;
}
else if (st1 != st2)
return false;
return true;
}
public static bool IsValidQName(string qname)
{
foreach(string part in qname.Split(new char[]{':'},2))
{
if(!CheckNCName(part))
return false;
}
return true;
}
//FIXME: First remove all the multiple instances of whitespace and then return the strings.
//The current method returns empty strings if there are two or more consecutive whitespaces.
public static string[] SplitList(string list)
{
if(list == null || list == string.Empty)
return new string [0];
string[] listarr = list.Split(new char[]{' ','\t','\n'});
int pos=0;
int i = 0;
for(i=0;i