PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System.XML/System.Xml.Schema/XmlSchemaUtil.cs

https://bitbucket.org/danipen/mono
C# | 700 lines | 600 code | 54 blank | 46 comment | 260 complexity | d5fd0b723bf0ef4e150033c0e01f05f0 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. //
  2. // Permission is hereby granted, free of charge, to any person obtaining
  3. // a copy of this software and associated documentation files (the
  4. // "Software"), to deal in the Software without restriction, including
  5. // without limitation the rights to use, copy, modify, merge, publish,
  6. // distribute, sublicense, and/or sell copies of the Software, and to
  7. // permit persons to whom the Software is furnished to do so, subject to
  8. // the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be
  11. // included in all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  15. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  17. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  18. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  19. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. //
  21. using System;
  22. using System.Xml;
  23. using System.Collections;
  24. using System.Text;
  25. using Mono.Xml;
  26. using Mono.Xml.Schema;
  27. using System.Xml.Serialization;
  28. namespace System.Xml.Schema
  29. {
  30. /// <summary>
  31. /// All Methods in this class should use XmlConvert. Some Methods are not present in the
  32. /// MS Implementation. We should provide them.
  33. /// </summary>
  34. internal class XmlSchemaUtil
  35. {
  36. static XmlSchemaUtil ()
  37. {
  38. FinalAllowed = XmlSchemaDerivationMethod.Restriction |
  39. XmlSchemaDerivationMethod.Extension;
  40. ComplexTypeBlockAllowed = FinalAllowed;
  41. ElementBlockAllowed = XmlSchemaDerivationMethod.Substitution |
  42. FinalAllowed;
  43. }
  44. internal static XmlSchemaDerivationMethod FinalAllowed;
  45. internal static XmlSchemaDerivationMethod ElementBlockAllowed;
  46. internal static XmlSchemaDerivationMethod ComplexTypeBlockAllowed;
  47. internal static readonly bool StrictMsCompliant = Environment.GetEnvironmentVariable ("MONO_STRICT_MS_COMPLIANT") == "yes";
  48. public static void AddToTable (XmlSchemaObjectTable table, XmlSchemaObject obj,
  49. XmlQualifiedName qname, ValidationEventHandler h)
  50. {
  51. if (table.Contains (qname)) {
  52. // FIXME: This logic unexpectedly allows
  53. // one redefining item and two or more redefining items.
  54. // FIXME: redefining item is not simple replacement,
  55. // but much more complex stuff.
  56. if (obj.isRedefineChild) { // take precedence.
  57. if (obj.redefinedObject != null)
  58. obj.error (h, String.Format ("Named item {0} was already contained in the schema object table.", qname));
  59. else
  60. obj.redefinedObject = table [qname];
  61. table.Set (qname, obj);
  62. }
  63. else if (table [qname].isRedefineChild) {
  64. if (table [qname].redefinedObject != null)
  65. obj.error (h, String.Format ("Named item {0} was already contained in the schema object table.", qname));
  66. else
  67. table [qname].redefinedObject = obj;
  68. return; // never add to the table.
  69. }
  70. else if (StrictMsCompliant) {
  71. table.Set (qname, obj);
  72. }
  73. else
  74. obj.error (h, String.Format ("Named item {0} was already contained in the schema object table. {1}",
  75. qname, "Consider setting MONO_STRICT_MS_COMPLIANT to 'yes' to mimic MS implementation."));
  76. }
  77. else
  78. table.Set (qname, obj);
  79. }
  80. public static void CompileID (string id, XmlSchemaObject xso, Hashtable idCollection, ValidationEventHandler h)
  81. {
  82. //check if the string conforms to http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/datatypes.html#ID
  83. // 1. ID must be a NCName
  84. // 2. ID must be unique in the schema
  85. if(id == null)
  86. return;
  87. if(!CheckNCName(id))
  88. xso.error(h,id+" is not a valid id attribute");
  89. else if(idCollection.ContainsKey(id))
  90. xso.error(h,"Duplicate id attribute "+id);
  91. else
  92. idCollection.Add(id,xso);
  93. }
  94. public static bool CheckAnyUri (string uri)
  95. {
  96. if (uri.StartsWith ("##"))
  97. return false;
  98. return true;
  99. }
  100. public static bool CheckNormalizedString (string token)
  101. {
  102. return true;
  103. }
  104. public static bool CheckNCName (string name)
  105. {
  106. //check if the string conforms to http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/datatypes.html#NCName
  107. return XmlChar.IsNCName (name);
  108. }
  109. public static bool CheckQName (XmlQualifiedName qname)
  110. {
  111. // What is this doing?
  112. return true;
  113. }
  114. public static XmlParserContext GetParserContext (XmlReader reader)
  115. {
  116. IHasXmlParserContext xctx = reader as IHasXmlParserContext;
  117. if (xctx != null)
  118. return xctx.ParserContext;
  119. return null;
  120. }
  121. public static bool IsBuiltInDatatypeName (XmlQualifiedName qname)
  122. {
  123. if (qname.Namespace == XmlSchema.XdtNamespace) {
  124. switch (qname.Name) {
  125. case "anyAtomicType":
  126. case "untypedAtomic":
  127. case "dayTimeDuration":
  128. case "yearMonthDuration":
  129. return true;
  130. default:
  131. return false;
  132. }
  133. }
  134. if (qname.Namespace != XmlSchema.Namespace)
  135. return false;
  136. switch (qname.Name) {
  137. case "anySimpleType":
  138. case "duration": case "dateTime": case "time":
  139. case "date": case "gYearMonth": case "gYear":
  140. case "gMonthDay": case "gDay": case "gMonth":
  141. case "boolean":
  142. case "base64Binary": case "hexBinary":
  143. case "float": case "double":
  144. case "anyURI":
  145. case "QName":
  146. case "NOTATION":
  147. case "string": case "normalizedString": case "token":
  148. case "language": case "Name": case "NCName":
  149. case "ID": case "IDREF": case "IDREFS":
  150. case "ENTITY": case "ENTITIES":
  151. case "NMTOKEN": case "NMTOKENS":
  152. case "decimal": case "integer":
  153. case "nonPositiveInteger": case "negativeInteger":
  154. case "nonNegativeInteger":
  155. case "unsignedLong": case "unsignedInt":
  156. case "unsignedShort": case "unsignedByte":
  157. case "positiveInteger":
  158. case "long": case "int": case "short": case "byte":
  159. return true;
  160. }
  161. return false;
  162. }
  163. public static bool AreSchemaDatatypeEqual (XmlSchemaSimpleType st1, object v1, XmlSchemaSimpleType st2, object v2)
  164. {
  165. if (st1.Datatype is XsdAnySimpleType)
  166. return AreSchemaDatatypeEqual (st1.Datatype as XsdAnySimpleType, v1, st2.Datatype as XsdAnySimpleType, v2);
  167. // otherwise the types are lists of strings.
  168. string [] a1 = v1 as string [];
  169. string [] a2 = v2 as string [];
  170. if (st1 != st2 || a1 == null || a2 == null || a1.Length != a2.Length)
  171. return false;
  172. for (int i = 0; i < a1.Length; i++)
  173. if (a1 [i] != a2 [i])
  174. return false;
  175. return true;
  176. }
  177. public static bool AreSchemaDatatypeEqual (XsdAnySimpleType st1, object v1,
  178. XsdAnySimpleType st2, object v2)
  179. {
  180. if (v1 == null || v2 == null)
  181. return false;
  182. if (st1 == null)
  183. st1 = XmlSchemaSimpleType.AnySimpleType;
  184. if (st2 == null)
  185. st2 = XmlSchemaSimpleType.AnySimpleType;
  186. Type t = st2.GetType ();
  187. if (st1 is XsdFloat) {
  188. return st2 is XsdFloat && Convert.ToSingle (v1) == Convert.ToSingle (v2);
  189. } else if (st1 is XsdDouble) {
  190. return st2 is XsdDouble && Convert.ToDouble (v1) == Convert.ToDouble (v2);
  191. } else if (st1 is XsdDecimal) {
  192. if (!(st2 is XsdDecimal) || Convert.ToDecimal (v1) != Convert.ToDecimal (v2))
  193. return false;
  194. if (st1 is XsdNonPositiveInteger)
  195. return st2 is XsdNonPositiveInteger || t == typeof (XsdDecimal) || t == typeof (XsdInteger);
  196. else if (st1 is XsdPositiveInteger)
  197. return st2 is XsdPositiveInteger || t == typeof (XsdDecimal) ||
  198. t == typeof (XsdInteger) || t == typeof (XsdNonNegativeInteger);
  199. else if (st1 is XsdUnsignedLong)
  200. return st2 is XsdUnsignedLong || t == typeof (XsdDecimal) ||
  201. t == typeof (XsdInteger) || t == typeof (XsdNonNegativeInteger);
  202. else if (st1 is XsdNonNegativeInteger)
  203. return st2 is XsdNonNegativeInteger || t == typeof (XsdDecimal) || t == typeof (XsdInteger);
  204. else if (st1 is XsdLong)
  205. return st2 is XsdLong || t == typeof (XsdDecimal) || t == typeof (XsdInteger);
  206. return true;
  207. }
  208. else if (!v1.Equals (v2))
  209. return false;
  210. if (st1 is XsdString) {
  211. if (!(st2 is XsdString))
  212. return false;
  213. if (st1 is XsdNMToken && (st2 is XsdLanguage || st2 is XsdName))
  214. return false;
  215. if (st2 is XsdNMToken && (st1 is XsdLanguage || st1 is XsdName))
  216. return false;
  217. if (st1 is XsdName && (st2 is XsdLanguage || st2 is XsdNMToken))
  218. return false;
  219. if (st2 is XsdName && (st1 is XsdLanguage || st1 is XsdNMToken))
  220. return false;
  221. if (st1 is XsdID && st2 is XsdIDRef)
  222. return false;
  223. if (st1 is XsdIDRef && st2 is XsdID)
  224. return false;
  225. }
  226. else if (st1 != st2)
  227. return false;
  228. return true;
  229. }
  230. public static bool IsValidQName(string qname)
  231. {
  232. foreach(string part in qname.Split(new char[]{':'},2))
  233. {
  234. if(!CheckNCName(part))
  235. return false;
  236. }
  237. return true;
  238. }
  239. //FIXME: First remove all the multiple instances of whitespace and then return the strings.
  240. //The current method returns empty strings if there are two or more consecutive whitespaces.
  241. public static string[] SplitList(string list)
  242. {
  243. if(list == null || list == string.Empty)
  244. return new string [0];
  245. ArrayList al = null;
  246. int start = 0;
  247. bool wait = true;
  248. for (int i = 0; i < list.Length; i++) {
  249. switch (list [i]) {
  250. case ' ':
  251. case '\r':
  252. case '\n':
  253. case '\t':
  254. if (!wait) {
  255. if (al == null)
  256. al = new ArrayList ();
  257. al.Add (list.Substring (start, i - start));
  258. }
  259. wait = true;
  260. break;
  261. default:
  262. if (wait) {
  263. wait = false;
  264. start = i;
  265. }
  266. break;
  267. }
  268. }
  269. if (!wait && start == 0)
  270. return new string [] {list};
  271. if (!wait && start < list.Length)
  272. al.Add (start == 0 ? list : list.Substring (start));
  273. return al.ToArray (typeof (string)) as string [];
  274. }
  275. public static void ReadUnhandledAttribute(XmlReader reader, XmlSchemaObject xso)
  276. {
  277. if(reader.Prefix == "xmlns")
  278. xso.Namespaces.Add(reader.LocalName, reader.Value);
  279. else if(reader.Name == "xmlns")
  280. xso.Namespaces.Add("",reader.Value);
  281. else
  282. {
  283. if(xso.unhandledAttributeList == null)
  284. xso.unhandledAttributeList = new System.Collections.ArrayList();
  285. XmlAttribute attr = new XmlDocument().CreateAttribute(reader.LocalName,reader.NamespaceURI);
  286. attr.Value = reader.Value;
  287. ParseWsdlArrayType (reader, attr);
  288. xso.unhandledAttributeList.Add(attr);
  289. }
  290. }
  291. static void ParseWsdlArrayType (XmlReader reader, XmlAttribute attr)
  292. {
  293. if (attr.NamespaceURI == XmlSerializer.WsdlNamespace && attr.LocalName == "arrayType")
  294. {
  295. string ns = "", type, dimensions;
  296. TypeTranslator.ParseArrayType (attr.Value, out type, out ns, out dimensions);
  297. if (ns != "") ns = reader.LookupNamespace (ns) + ":";
  298. attr.Value = ns + type + dimensions;
  299. }
  300. }
  301. public static bool ReadBoolAttribute(XmlReader reader, out Exception innerExcpetion)
  302. {
  303. innerExcpetion = null;
  304. try
  305. {
  306. bool val = XmlConvert.ToBoolean(reader.Value);
  307. return val;
  308. }
  309. catch(Exception ex)
  310. {
  311. innerExcpetion = ex;
  312. return false;
  313. }
  314. }
  315. public static decimal ReadDecimalAttribute(XmlReader reader, out Exception innerExcpetion)
  316. {
  317. innerExcpetion = null;
  318. try
  319. {
  320. decimal val = XmlConvert.ToDecimal(reader.Value);
  321. return val;
  322. }
  323. catch(Exception ex)
  324. {
  325. innerExcpetion = ex;
  326. return decimal.Zero;
  327. }
  328. }
  329. // Is some value is read, return it.
  330. // If no values return empty.
  331. // If exception, return none
  332. public static XmlSchemaDerivationMethod ReadDerivationAttribute(XmlReader reader, out Exception innerExcpetion, string name, XmlSchemaDerivationMethod allowed)
  333. {
  334. innerExcpetion = null;
  335. try
  336. {
  337. string list = reader.Value;
  338. string warn = "";
  339. XmlSchemaDerivationMethod val = 0;
  340. if(list.IndexOf("#all") != -1 && list.Trim() != "#all")
  341. {
  342. innerExcpetion = new Exception(list+" is not a valid value for "+ name +". #all if present must be the only value");
  343. return XmlSchemaDerivationMethod.All;
  344. }
  345. foreach(string xsdm in XmlSchemaUtil.SplitList(list))
  346. {
  347. switch(xsdm)
  348. {
  349. case "":
  350. val = AddFlag (val, XmlSchemaDerivationMethod.Empty, allowed); break;
  351. case "#all":
  352. val = AddFlag (val,XmlSchemaDerivationMethod.All, allowed); break;
  353. case "substitution":
  354. val = AddFlag (val,XmlSchemaDerivationMethod.Substitution, allowed); break;
  355. case "extension":
  356. val = AddFlag (val,XmlSchemaDerivationMethod.Extension, allowed); break;
  357. case "restriction":
  358. val = AddFlag (val,XmlSchemaDerivationMethod.Restriction, allowed); break;
  359. case "list":
  360. val = AddFlag (val,XmlSchemaDerivationMethod.List, allowed); break;
  361. case "union":
  362. val = AddFlag (val,XmlSchemaDerivationMethod.Union, allowed); break;
  363. default:
  364. warn += xsdm + " "; break;
  365. }
  366. }
  367. if(warn != "")
  368. innerExcpetion = new Exception(warn + "is/are not valid values for " + name);
  369. return val;
  370. }
  371. catch(Exception ex)
  372. {
  373. innerExcpetion = ex;
  374. return XmlSchemaDerivationMethod.None;
  375. }
  376. }
  377. private static XmlSchemaDerivationMethod AddFlag (XmlSchemaDerivationMethod dst,
  378. XmlSchemaDerivationMethod add, XmlSchemaDerivationMethod allowed)
  379. {
  380. if ((add & allowed) == 0 && allowed != XmlSchemaDerivationMethod.All)
  381. throw new ArgumentException (add + " is not allowed in this attribute.");
  382. if ((dst & add) != 0)
  383. throw new ArgumentException (add + " is already specified in this attribute.");
  384. return dst | add;
  385. }
  386. public static XmlSchemaForm ReadFormAttribute(XmlReader reader, out Exception innerExcpetion)
  387. {
  388. innerExcpetion = null;
  389. XmlSchemaForm val = XmlSchemaForm.None;
  390. switch(reader.Value != null ? reader.Value.Trim () : null)
  391. {
  392. case "qualified":
  393. val = XmlSchemaForm.Qualified; break;
  394. case "unqualified":
  395. val = XmlSchemaForm.Unqualified; break;
  396. default:
  397. innerExcpetion = new Exception("only qualified or unqulified is a valid value"); break;
  398. }
  399. return val;
  400. }
  401. public static XmlSchemaContentProcessing ReadProcessingAttribute(XmlReader reader, out Exception innerExcpetion)
  402. {
  403. innerExcpetion = null;
  404. XmlSchemaContentProcessing val = XmlSchemaContentProcessing.None;
  405. switch(reader.Value != null ? reader.Value.Trim () : null)
  406. {
  407. case "lax":
  408. val = XmlSchemaContentProcessing.Lax; break;
  409. case "strict":
  410. val = XmlSchemaContentProcessing.Strict; break;
  411. case "skip":
  412. val = XmlSchemaContentProcessing.Skip; break;
  413. default:
  414. innerExcpetion = new Exception("only lax , strict or skip are valid values for processContents");
  415. break;
  416. }
  417. return val;
  418. }
  419. public static XmlSchemaUse ReadUseAttribute(XmlReader reader, out Exception innerExcpetion)
  420. {
  421. innerExcpetion = null;
  422. XmlSchemaUse val = XmlSchemaUse.None;
  423. switch(reader.Value != null ? reader.Value.Trim () : null)
  424. {
  425. case "optional":
  426. val = XmlSchemaUse.Optional; break;
  427. case "prohibited":
  428. val = XmlSchemaUse.Prohibited; break;
  429. case "required":
  430. val = XmlSchemaUse.Required; break;
  431. default:
  432. innerExcpetion = new Exception("only optional , prohibited or required are valid values for use");
  433. break;
  434. }
  435. return val;
  436. }
  437. public static XmlQualifiedName ReadQNameAttribute(XmlReader reader, out Exception innerEx)
  438. {
  439. return ToQName(reader, reader.Value, out innerEx);
  440. }
  441. //While Creating a XmlQualifedName, we should check:
  442. // 1. If a prefix is present, its namespace should be resolvable.
  443. // 2. If a prefix is not present, and if the defaultNamespace is set,
  444. public static XmlQualifiedName ToQName(XmlReader reader, string qnamestr, out Exception innerEx)
  445. {
  446. string ns;
  447. string name;
  448. XmlQualifiedName qname;
  449. innerEx = null;
  450. if(!IsValidQName(qnamestr))
  451. {
  452. innerEx = new Exception(qnamestr + " is an invalid QName. Either name or namespace is not a NCName");
  453. return XmlQualifiedName.Empty;
  454. }
  455. string[] values = qnamestr.Split(new char[]{':'},2);
  456. if(values.Length == 2)
  457. {
  458. ns = reader.LookupNamespace(values[0]);
  459. if(ns == null)
  460. {
  461. innerEx = new Exception("Namespace Prefix '"+values[0]+"could not be resolved");
  462. return XmlQualifiedName.Empty;
  463. }
  464. name = values[1];
  465. }
  466. else
  467. {
  468. //Default Namespace
  469. ns = reader.LookupNamespace("");
  470. name = values[0];
  471. }
  472. qname = new XmlQualifiedName(name,ns);
  473. return qname;
  474. }
  475. public static int ValidateAttributesResolved (
  476. XmlSchemaObjectTable attributesResolved,
  477. ValidationEventHandler h,
  478. XmlSchema schema,
  479. XmlSchemaObjectCollection attributes,
  480. XmlSchemaAnyAttribute anyAttribute,
  481. ref XmlSchemaAnyAttribute anyAttributeUse,
  482. XmlSchemaAttributeGroup redefined,
  483. bool skipEquivalent)
  484. {
  485. int errorCount = 0;
  486. if (anyAttribute != null && anyAttributeUse == null)
  487. anyAttributeUse = anyAttribute;
  488. ArrayList newAttrNames = new ArrayList ();
  489. foreach (XmlSchemaObject xsobj in attributes) {
  490. XmlSchemaAttributeGroupRef grpRef = xsobj as XmlSchemaAttributeGroupRef;
  491. if (grpRef != null) {
  492. // Resolve attributeGroup redefinition.
  493. XmlSchemaAttributeGroup grp = null;
  494. if (redefined != null && grpRef.RefName == redefined.QualifiedName)
  495. grp = redefined;
  496. else
  497. grp = schema.FindAttributeGroup (grpRef.RefName);
  498. // otherwise, it might be missing sub components.
  499. if (grp == null) {
  500. if (!schema.missedSubComponents)// && schema.Schemas [grpRef.RefName.Namespace] != null)
  501. grpRef.error (h, "Referenced attribute group " + grpRef.RefName + " was not found in the corresponding schema.");
  502. continue;
  503. }
  504. if (grp.AttributeGroupRecursionCheck) {
  505. grp.error (h, "Attribute group recursion was found: " + grpRef.RefName);
  506. continue;
  507. }
  508. try {
  509. grp.AttributeGroupRecursionCheck = true;
  510. errorCount += grp.Validate (h, schema);
  511. } finally {
  512. grp.AttributeGroupRecursionCheck = false;
  513. }
  514. if (grp.AnyAttributeUse != null) {
  515. if (anyAttribute == null)
  516. anyAttributeUse = grp.AnyAttributeUse;
  517. }
  518. foreach (DictionaryEntry entry in grp.AttributeUses) {
  519. XmlSchemaAttribute attr = (XmlSchemaAttribute) entry.Value;
  520. if (StrictMsCompliant && attr.Use == XmlSchemaUse.Prohibited)
  521. continue;
  522. if (attr.RefName != null && attr.RefName != XmlQualifiedName.Empty && (!skipEquivalent || !AreAttributesEqual (attr, attributesResolved [attr.RefName] as XmlSchemaAttribute)))
  523. AddToTable (attributesResolved, attr, attr.RefName, h);
  524. else if (!skipEquivalent || !AreAttributesEqual (attr, attributesResolved [attr.QualifiedName] as XmlSchemaAttribute))
  525. AddToTable (attributesResolved, attr, attr.QualifiedName, h);
  526. }
  527. } else {
  528. XmlSchemaAttribute attr = xsobj as XmlSchemaAttribute;
  529. if (attr != null) {
  530. errorCount += attr.Validate (h, schema);
  531. if (newAttrNames.Contains (attr.QualifiedName))
  532. attr.error (h, String.Format ("Duplicate attributes was found for '{0}'", attr.QualifiedName));
  533. newAttrNames.Add (attr.QualifiedName);
  534. if (StrictMsCompliant && attr.Use == XmlSchemaUse.Prohibited)
  535. continue;
  536. if (attr.RefName != null && attr.RefName != XmlQualifiedName.Empty && (!skipEquivalent || !AreAttributesEqual (attr, attributesResolved [attr.RefName] as XmlSchemaAttribute)))
  537. AddToTable (attributesResolved, attr, attr.RefName, h);
  538. else if (!skipEquivalent || !AreAttributesEqual (attr, attributesResolved [attr.QualifiedName] as XmlSchemaAttribute))
  539. AddToTable (attributesResolved, attr, attr.QualifiedName, h);
  540. } else {
  541. if (anyAttribute != null) {
  542. anyAttributeUse = (XmlSchemaAnyAttribute) xsobj;
  543. anyAttribute.Validate (h, schema);
  544. }
  545. }
  546. }
  547. }
  548. return errorCount;
  549. }
  550. internal static bool AreAttributesEqual (XmlSchemaAttribute one,
  551. XmlSchemaAttribute another)
  552. {
  553. if (one == null || another == null)
  554. return false;
  555. return one.AttributeType == another.AttributeType &&
  556. one.Form == another.Form &&
  557. one.ValidatedUse == another.ValidatedUse &&
  558. one.ValidatedDefaultValue == another.ValidatedDefaultValue &&
  559. one.ValidatedFixedValue == another.ValidatedFixedValue;
  560. }
  561. #if NET_2_0
  562. public static object ReadTypedValue (XmlReader reader,
  563. object type, IXmlNamespaceResolver nsResolver,
  564. StringBuilder tmpBuilder)
  565. #else
  566. public static object ReadTypedValue (XmlReader reader,
  567. object type, XmlNamespaceManager nsResolver,
  568. StringBuilder tmpBuilder)
  569. #endif
  570. {
  571. if (tmpBuilder == null)
  572. tmpBuilder = new StringBuilder ();
  573. XmlSchemaDatatype dt = type as XmlSchemaDatatype;
  574. XmlSchemaSimpleType st = type as XmlSchemaSimpleType;
  575. if (st != null)
  576. dt = st.Datatype;
  577. if (dt == null)
  578. return null;
  579. switch (reader.NodeType) {
  580. case XmlNodeType.Element:
  581. if (reader.IsEmptyElement)
  582. return null;
  583. tmpBuilder.Length = 0;
  584. bool loop = true;
  585. do {
  586. reader.Read ();
  587. switch (reader.NodeType) {
  588. case XmlNodeType.SignificantWhitespace:
  589. case XmlNodeType.Text:
  590. case XmlNodeType.CDATA:
  591. tmpBuilder.Append (reader.Value);
  592. break;
  593. case XmlNodeType.Comment:
  594. break;
  595. default:
  596. loop = false;
  597. break;
  598. }
  599. } while (loop && !reader.EOF && reader.ReadState == ReadState.Interactive);
  600. return dt.ParseValue (tmpBuilder.ToString (), reader.NameTable, nsResolver);
  601. case XmlNodeType.Attribute:
  602. return dt.ParseValue (reader.Value, reader.NameTable, nsResolver);
  603. }
  604. return null;
  605. }
  606. public static XmlSchemaObject FindAttributeDeclaration (
  607. string ns,
  608. XmlSchemaSet schemas,
  609. XmlSchemaComplexType cType,
  610. XmlQualifiedName qname)
  611. {
  612. XmlSchemaObject result = cType.AttributeUses [qname];
  613. if (result != null)
  614. return result;
  615. if (cType.AttributeWildcard == null)
  616. return null;
  617. if (!AttributeWildcardItemValid (cType.AttributeWildcard, qname, ns))
  618. return null;
  619. if (cType.AttributeWildcard.ResolvedProcessContents == XmlSchemaContentProcessing.Skip)
  620. return cType.AttributeWildcard;
  621. XmlSchemaAttribute attr = schemas.GlobalAttributes [qname] as XmlSchemaAttribute;
  622. if (attr != null)
  623. return attr;
  624. if (cType.AttributeWildcard.ResolvedProcessContents == XmlSchemaContentProcessing.Lax)
  625. return cType.AttributeWildcard;
  626. else
  627. return null;
  628. }
  629. // Spec 3.10.4 Item Valid (Wildcard)
  630. private static bool AttributeWildcardItemValid (XmlSchemaAnyAttribute anyAttr, XmlQualifiedName qname, string ns)
  631. {
  632. if (anyAttr.HasValueAny)
  633. return true;
  634. if (anyAttr.HasValueOther && (anyAttr.TargetNamespace == "" || ns != anyAttr.TargetNamespace))
  635. return true;
  636. if (anyAttr.HasValueTargetNamespace && ns == anyAttr.TargetNamespace)
  637. return true;
  638. if (anyAttr.HasValueLocal && ns == "")
  639. return true;
  640. for (int i = 0; i < anyAttr.ResolvedNamespaces.Count; i++)
  641. if (anyAttr.ResolvedNamespaces [i] == ns)
  642. return true;
  643. return false;
  644. }
  645. }
  646. }