// 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;
}
}
}