// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.CodeDom; using System.CodeDom.Compiler; using System.IO; using System.Xml; using System.Xml.Schema; namespace System.Runtime.Serialization.Schema.Tests { internal class SchemaUtils { static XmlWriterSettings writerSettings = new XmlWriterSettings() { Indent = true }; #region Test Data private static string[] _positiveSchemas = new string[] { @" ", @" ", @" ", }; internal static XmlSchemaSet PositiveSchemas => ReadStringsIntoSchemaSet(_positiveSchemas); private static string[] _isReferenceSchemas = new string[] { @" ", @" ", }; internal static XmlSchemaSet IsReferenceSchemas => ReadStringsIntoSchemaSet(_isReferenceSchemas); private static string[] _mixedSchemas = new string[] { @" ", @" ", }; internal static XmlSchemaSet MixedSchemas => ReadStringsIntoSchemaSet(_mixedSchemas); internal static string[] NegativeSchemaStrings = new string[] { @"", // null @" ", // new XmlQualifiedName("FooType", "http://EmptySchema"), @" ", // new XmlQualifiedName("FooType", "http://NonExistantSchema"), @" ", // null @" ", // null @" ", // new XmlQualifiedName("ExtraAttributeWildcardType", "http://schemas.datacontract.org/2004/07/foo"), @" ", // null @" ", // null @" ", // null @" ", // null @" ", // null @" ", // null @" ", // null @" ", // null @" ", // null }; internal static (bool expectedResult, bool isElement, XmlQualifiedName[] qnames, string schemaString)[] CanImportTests = new (bool, bool, XmlQualifiedName[], string)[] { (false, false, new XmlQualifiedName[] { new XmlQualifiedName("InvalidTopLevelElementType", "http://schemas.datacontract.org/2004/07/foo") }, @" "), (true, false, new XmlQualifiedName[] { new XmlQualifiedName("ValidType", "http://schemas.datacontract.org/2004/07/foo") }, @" "), (true, false, new XmlQualifiedName[] { new XmlQualifiedName("Address", "http://schemas.datacontract.org/2004/07/Suites.SchemaImport.Classes"), new XmlQualifiedName("Person", "http://schemas.datacontract.org/2004/07/Suites.SchemaImport.Classes"), new XmlQualifiedName("ArrayOfAddress", "http://schemas.datacontract.org/2004/07/Suites.SchemaImport.Classes"), new XmlQualifiedName("ArrayOfArrayOfAddress", "http://schemas.datacontract.org/2004/07/Suites.SchemaImport.Classes"), }, @" "), (true, false, null, @" "), (true, false, null, @" "), (false, false, new XmlQualifiedName[] { new XmlQualifiedName("TypeWithExtraAttributes", "http://schemas.datacontract.org/2004/07/foo") }, @" "), (true, true, new XmlQualifiedName[] { new XmlQualifiedName("Address", "http://schemas.datacontract.org/2004/07/Suites.SchemaImport.Classes") }, @" "), }; internal static XmlQualifiedName[] ValidTypeNames = new XmlQualifiedName[] { new XmlQualifiedName("ValidType", "http://schemas.datacontract.org/2004/07/fooNs"), new XmlQualifiedName("AnotherValidType", "http://schemas.datacontract.org/2004/07/barNs"), new XmlQualifiedName("NonAttributedType", "http://schemas.datacontract.org/2004/07/Suites.SchemaImport"), new XmlQualifiedName("NonRefType", "http://schemas.datacontract.org/2004/07/Suites.SchemaImport.ReferencedTypes"), new XmlQualifiedName("RefType1", "http://schemas.datacontract.org/2004/07/Suites.SchemaImport.ReferencedTypes"), }; internal static XmlQualifiedName[] InvalidTypeNames = new XmlQualifiedName[] { new XmlQualifiedName("InvalidType", "http://schemas.datacontract.org/2004/07/fooNs"), }; // These correspond with the set in 'NegativeSchemaStrings' internal static XmlQualifiedName[] NegativeTypeNames = new XmlQualifiedName[] { null, new XmlQualifiedName("FooType", "http://EmptySchema"), new XmlQualifiedName("FooType", "http://NonExistantSchema"), null, null, new XmlQualifiedName("ExtraAttributeWildcardType", "http://schemas.datacontract.org/2004/07/foo"), null, null, null, null, null, null, null, null, null, }; internal static string GlobalSchema = @" "; #endregion internal static XsdDataContractImporter CreateImporterWithDefaultOptions() { XsdDataContractImporter importer = new XsdDataContractImporter(); importer.Options = new ImportOptions(); return importer; } internal static string DumpCode(CodeCompileUnit ccu, CodeDomProvider provider = null) { provider ??= CodeDomProvider.CreateProvider("csharp"); CodeGeneratorOptions options = new CodeGeneratorOptions() { BlankLinesBetweenMembers = true, BracingStyle = "C", }; StringWriter sw = new StringWriter(); provider.GenerateCodeFromCompileUnit(ccu, sw, options); return sw.ToString(); } internal static XmlSchema GetSchema(XmlSchemaSet schemaSet, string targetNs) { XmlSchema schema = null; foreach (XmlSchema ctSchema in schemaSet.Schemas()) { if (ctSchema.TargetNamespace == targetNs) { schema = ctSchema; break; } } return schema; } internal static XmlSchemaElement GetSchemaElement(XmlSchemaSet schemaSet, XmlQualifiedName qname) { foreach (XmlSchema schema in schemaSet.Schemas(qname.Namespace)) { XmlSchemaElement schemaElement = (XmlSchemaElement)schema.Elements[qname]; if (schemaElement != null) return schemaElement; } throw new Exception(String.Format("Element {0} is not found", qname)); } internal static string GetSchemaString(XmlSchemaSet schemaSet, string targetNs) { XmlSchema schema = GetSchema(schemaSet, targetNs); StringWriter stringWriter = new StringWriter(); XmlWriter xmlWriter = XmlWriter.Create(stringWriter, writerSettings); schema.Write(xmlWriter); xmlWriter.Flush(); return stringWriter.ToString(); } internal static void SetSchemaString(XmlSchemaSet schemaSet, string targetNs, string schemaString) { XmlSchema schema = null; foreach (XmlSchema ctSchema in schemaSet.Schemas()) { if (ctSchema.TargetNamespace == targetNs) { schema = ctSchema; break; } } schemaSet.Remove(schema); schema = XmlSchema.Read(new StringReader(schemaString), null); schemaSet.Add(schema); } internal static string GetString(CodeTypeReference typeReference) { if (typeReference.ArrayRank > 0) { CodeTypeReference arrayType = typeReference; string arrayString = String.Empty; for (; ; ) { int rank = typeReference.ArrayRank; arrayString += "["; for (int r = 1; r < rank; r++) arrayString += ","; arrayString += "]"; typeReference = typeReference.ArrayElementType; if (typeReference.ArrayRank == 0) break; } return String.Format("Array of {0}{1}", typeReference.BaseType, arrayString); } else return typeReference.BaseType; } internal static string InsertAttribute(string xml, string xpath, string prefix, string localName, string ns, string value) { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(XmlReader.Create(new StringReader(xml))); XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmlDoc.NameTable); nsMgr.AddNamespace("xs", XmlSchema.Namespace); XmlElement xmlElement = (XmlElement)xmlDoc.SelectSingleNode(xpath, nsMgr); XmlAttribute xmlAttribute = xmlDoc.CreateAttribute(prefix, localName, ns); xmlAttribute.Value = value; xmlElement.Attributes.Append(xmlAttribute); StringWriter stringWriter = new StringWriter(); xmlDoc.Save(XmlWriter.Create(stringWriter, writerSettings)); return stringWriter.ToString(); } internal static string InsertElement(string xml, string xpath, string xmlFrag, bool insertAfter) { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(XmlReader.Create(new StringReader(xml))); XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmlDoc.NameTable); nsMgr.AddNamespace("xs", XmlSchema.Namespace); XmlNode xmlNode = xmlDoc.SelectSingleNode(xpath, nsMgr); if (insertAfter) xmlNode.ParentNode.InsertAfter(xmlDoc.ReadNode(XmlReader.Create(new StringReader(xmlFrag))), xmlNode); else xmlNode.ParentNode.InsertBefore(xmlDoc.ReadNode(XmlReader.Create(new StringReader(xmlFrag))), xmlNode); StringWriter stringWriter = new StringWriter(); xmlDoc.Save(XmlWriter.Create(stringWriter, writerSettings)); return stringWriter.ToString(); } internal static XmlSchemaSet ReadStringsIntoSchemaSet(params string[] schemaStrings) { XmlSchemaSet schemaSet = new XmlSchemaSet(); foreach (string schemaString in schemaStrings) { StringReader reader = new StringReader(schemaString); XmlSchema schema = XmlSchema.Read(reader, null); if (schema == null) throw new Exception("Could not read schema"); schemaSet.Add(schema); } return schemaSet; } } }