Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataWeb / Design / system / Data / Services / Design / Xml / XNodeSchemaApplier.cs / 1305376 / XNodeSchemaApplier.cs
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Provides a class used to make an XElement conform to a given
// XML Schema.
//
//
// @owner [....]
//---------------------------------------------------------------------
namespace System.Data.Services.Design.Xml
{
#region Namespaces.
using System.Diagnostics;
using System;
using System.Linq;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Runtime.Versioning;
#endregion Namespaces.
/// Use this class to remove unexpected elements and attributes from an XDocument instance.
internal class XNodeSchemaApplier
{
#region Private fields.
/// Namespace manager for current scope.
private readonly XmlNamespaceManager namespaceManager;
/// Schemas used to predict expected elements and attributes.
private readonly XmlSchemaSet schemas;
/// XName for xsi:type.
private readonly XName xsiTypeName;
/// XName for xsi:nil.
private readonly XName xsiNilName;
/// Schema validator used to predict expected elements and attributes.
private XmlSchemaValidator validator;
#endregion Private fields.
#region Constructors.
/// Initializes a new instance.
/// Schemas to use to predict elements and attributes.
private XNodeSchemaApplier(XmlSchemaSet schemas)
{
Debug.Assert(schemas != null, "schemas != null");
this.schemas = schemas;
XNamespace xsi = XNamespace.Get("http://www.w3.org/2001/XMLSchema-instance");
this.xsiTypeName = xsi.GetName("type");
this.xsiNilName = xsi.GetName("nil");
this.namespaceManager = new XmlNamespaceManager(schemas.NameTable);
}
#endregion Constructors.
#region Internal methods.
///
/// Appends to the specified , creating as necessary.
///
/// List element type.
/// List to add the element to, possibly null on entry.
/// Element to add to the list.
internal static void AppendWithCreation(ref List list, T element)
{
if (list == null)
{
list = new List();
}
list.Add(element);
}
///
/// Applies the specified to remove unexpected elements and attributes from the
/// given .
///
/// Set of schemas to apply.
/// Document to remove elements and attributes from.
internal static void Apply(XmlSchemaSet schemas, XElement element)
{
Debug.Assert(schemas != null, "schemas != null");
Debug.Assert(element != null, "document != null");
XNodeSchemaApplier applier = new XNodeSchemaApplier(schemas);
applier.Validate(element);
}
#endregion Internal methods.
#region Private methods.
/// Determines whether the specified is expected.
/// Element to check.
///
/// of the (passed to avoid recreation).
///
/// Expected schema particle.
/// true if the element is expected; false otherwise.
private static bool IsElementExpected(XElement element, XmlQualifiedName elementName, XmlSchemaParticle expected)
{
Debug.Assert(element != null, "element != null");
Debug.Assert(elementName != null, "elementName != null");
Debug.Assert(expected != null, "expected != null");
Debug.Assert(
ToQualifiedName(element.Name) == elementName,
"ToQualifiedName(element.Name) == elementName -- otherwise the caller get the 'caching' wrong");
// These are all possibilities for a particle.
XmlSchemaGroupRef schemaGroupRef = expected as XmlSchemaGroupRef;
XmlSchemaAny schemaAny = expected as XmlSchemaAny;
XmlSchemaElement schemaElement = expected as XmlSchemaElement;
XmlSchemaAll schemaAll = expected as XmlSchemaAll;
XmlSchemaChoice schemaChoice = expected as XmlSchemaChoice;
XmlSchemaSequence schemaSequence = expected as XmlSchemaSequence;
Debug.Assert(schemaGroupRef == null, "schemaGroupRef == null -- the validator flattens this out as options.");
Debug.Assert(schemaSequence == null, "schemaSequence == null -- the validator flattens this out and picks the right one in seq.");
Debug.Assert(schemaAll == null, "schemaAll == null -- the validator flattens this out as options.");
Debug.Assert(schemaChoice == null, "schemaChoice == null -- the validator flattens this out as options.");
if (schemaAny != null)
{
Debug.Assert(
schemaAny.Namespace == "##other" || schemaAny.Namespace == "##any",
"schemaAny.Namespace == '##other' || '##any' -- otherwise CSDL XSD resource was changed");
if (schemaAny.Namespace == "##any")
{
return true;
}
else if (schemaAny.Namespace == "##other")
{
string realElementNamespace = element.Name.NamespaceName;
if (realElementNamespace != GetTargetNamespace(expected))
{
return true;
}
}
}
if (schemaElement != null)
{
if (schemaElement.QualifiedName == elementName)
{
return true;
}
}
return false;
}
/// Gets the target namespace that applies to the specified .
/// XML schema object for which to get target namespace.
/// Target namespace for the specified (never null).
private static string GetTargetNamespace(XmlSchemaObject schemaObject)
{
Debug.Assert(schemaObject != null, "schemaObject != null");
string result = null;
do
{
XmlSchema schema = schemaObject as XmlSchema;
if (schema != null)
{
result = schema.TargetNamespace;
Debug.Assert(!String.IsNullOrEmpty(schema.TargetNamespace), "schema.TargetNamespace != null||'' -- otherwise this isn't CSDL");
}
else
{
schemaObject = schemaObject.Parent;
Debug.Assert(schemaObject != null, "o != null -- otherwise the object isn't parented to a schema");
}
}
while (result == null);
return result;
}
/// Determines whether the specified is expected.
/// Element to check.
/// Expected schema particles (possibly empty).
/// true if the element is expected; false otherwise.
private static bool IsElementExpected(XElement element, XmlSchemaParticle[] expectedParticles)
{
Debug.Assert(element != null, "element != null");
Debug.Assert(expectedParticles != null, "expectedParticles != null");
XmlQualifiedName elementName = ToQualifiedName(element.Name);
foreach (var expected in expectedParticles)
{
if (IsElementExpected(element, elementName, expected))
{
return true;
}
}
return false;
}
/// Determines whether the specified is expected.
/// Attribute to check.
/// Expected attributes (possibly empty).
/// anyAttribute schema for a complex type element (possibly null).
/// true if the attribute is expected; false otherwise.
private static bool IsAttributeExpected(XAttribute attribute, XmlSchemaAnyAttribute anyAttribute, XmlSchemaAttribute[] expectedAttributes)
{
Debug.Assert(attribute != null, "attribute != null");
Debug.Assert(expectedAttributes != null, "expectedAttributes != null");
Debug.Assert(expectedAttributes.All(a => a.Form != XmlSchemaForm.Qualified), "expectedAttributes.All(a => a.Form != XmlSchemaForm.Qualified)");
var name = ToQualifiedName(attribute.Name);
if (name.Namespace.Length == 0)
{
foreach (var expected in expectedAttributes)
{
if (expected.Name == name.Name)
{
return true;
}
}
}
if (anyAttribute != null)
{
Debug.Assert(
anyAttribute.Namespace == "##any" || anyAttribute.Namespace == "##other",
"anyAttribute.Namespace == '##any' || '##other' -- otherwise CSDL XSD resource was changed");
if (anyAttribute.Namespace == "##any")
{
return true;
}
else
{
string attributeNamespace = attribute.Name.NamespaceName;
if (attributeNamespace.Length > 0 && attributeNamespace != GetTargetNamespace(anyAttribute))
{
return true;
}
}
}
return false;
}
///
/// Return the representation of the specified .
///
/// XML name to return.
/// An that represents the given .
private static XmlQualifiedName ToQualifiedName(XName name)
{
Debug.Assert(name != null, "name != null");
return new XmlQualifiedName(name.LocalName, name.NamespaceName);
}
/// Validates the specified object.
/// Source object for validation (must be an element).
private void Validate(XElement element)
{
Debug.Assert(element != null, "element != null");
XmlSchemaValidationFlags validationFlags = XmlSchemaValidationFlags.AllowXmlAttributes;
this.PushAncestorsAndSelf(element.Parent);
validator = new XmlSchemaValidator(schemas.NameTable, schemas, namespaceManager, validationFlags);
validator.XmlResolver = null;
validator.Initialize();
this.ValidateElement(element);
validator.EndValidation();
}
/// Pushes the specifed namespaces and those of ancestors.
/// Element to push from - possibly null.
///
/// Pushing in reverse order (up the tree rather than down the tree) is OK, because we check that
/// the namespace local name hasn't been added yet. Use as we go down
/// the tree to push/pop as usual.
///
private void PushAncestorsAndSelf(XElement element)
{
while (element != null)
{
foreach (XAttribute attribute in element.Attributes())
{
if (attribute.IsNamespaceDeclaration)
{
string localName = attribute.Name.LocalName;
if (localName == "xmlns")
{
localName = string.Empty;
}
if (!namespaceManager.HasNamespace(localName))
{
namespaceManager.AddNamespace(localName, attribute.Value);
}
}
}
element = element.Parent as XElement;
}
}
/// Pushes the specifed namespaces and those of ancestors.
/// Element to push.
/// The value for xsi:type on this element.
/// The value for xsi:nil on this element.
private void PushElement(XElement element, ref string xsiType, ref string xsiNil)
{
Debug.Assert(element != null, "e != null");
namespaceManager.PushScope();
foreach (XAttribute attribute in element.Attributes())
{
if (attribute.IsNamespaceDeclaration)
{
string localName = attribute.Name.LocalName;
if (localName == "xmlns")
{
localName = string.Empty;
}
namespaceManager.AddNamespace(localName, attribute.Value);
}
else
{
XName name = attribute.Name;
if (name == xsiTypeName)
{
xsiType = attribute.Value;
}
else if (name == xsiNilName)
{
xsiNil = attribute.Value;
}
}
}
}
/// Validates all attributes on the specified .
/// Element to validate attributes on.
private void ValidateAttributes(XElement element)
{
Debug.Assert(element != null, "e != null");
foreach (XAttribute attribute in element.Attributes())
{
if (!attribute.IsNamespaceDeclaration)
{
validator.ValidateAttribute(attribute.Name.LocalName, attribute.Name.NamespaceName, attribute.Value, null);
}
}
}
//// SxS: This method does not expose any resources to the caller and passes null as resource names to
//// XmlSchemaValidator.ValidateElement (annotated with ResourceExposure(ResourceScope.None).
//// It's OK to suppress the SxS warning.
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
[ResourceExposure(ResourceScope.None)]
private void ValidateElement(XElement e)
{
Debug.Assert(e != null, "e != null");
XmlSchemaInfo schemaInfo = new XmlSchemaInfo();
string xsiType = null;
string xsiNil = null;
this.PushElement(e, ref xsiType, ref xsiNil);
// The current element is always valid - otherwise we wouldn't have recursed into it in the first place.
validator.ValidateElement(e.Name.LocalName, e.Name.NamespaceName, schemaInfo, xsiType, xsiNil, null, null);
// When we have no schema element, then e was included but we don't know about it - it's an extension
// element, likely under CSDL documentation. We'll skip the whole thing in this case.
if (schemaInfo.SchemaElement != null)
{
XmlSchemaComplexType schemaComplexType = schemaInfo.SchemaElement.ElementSchemaType as XmlSchemaComplexType;
this.TrimAttributes(e, (schemaComplexType == null) ? null : schemaComplexType.AttributeWildcard);
this.ValidateAttributes(e);
validator.ValidateEndOfAttributes(null);
this.TrimAndValidateNodes(e);
}
validator.ValidateEndElement(null);
this.namespaceManager.PopScope();
}
/// Removes attributes from the specified if they're unexpected.
/// Element to remove attributes from.
/// anyAttribute schema for a complex type element (possibly null).
private void TrimAttributes(XElement element, XmlSchemaAnyAttribute anyAttribute)
{
Debug.Assert(element != null, "e != null");
List unexpectedAttributes = null;
var expectedAttributes = validator.GetExpectedAttributes();
foreach (XAttribute attribute in element.Attributes())
{
if (attribute.IsNamespaceDeclaration)
{
continue;
}
if (!IsAttributeExpected(attribute, anyAttribute, expectedAttributes))
{
AppendWithCreation(ref unexpectedAttributes, attribute);
}
}
if (unexpectedAttributes != null)
{
foreach (var attribute in unexpectedAttributes)
{
attribute.Remove();
}
}
}
///
/// Removes nodes from the specified element and validates its nodes.
///
///
///
/// While it's cleaner to do this in two passes, trim then validate, like we do with attributes, we need to
/// validate as we go for the validator to return sequence elements in the right order.
///
private void TrimAndValidateNodes(XElement parent)
{
Debug.Assert(parent != null, "parent != null");
List unexpectedNodes = null;
XmlSchemaParticle[] expectedParticles = null;
foreach (XNode node in parent.Nodes())
{
// expectedParticles will be null the first iteration and right after we validate,
// when we potentially have something different to validate against.
if (expectedParticles == null)
{
expectedParticles = validator.GetExpectedParticles();
}
Debug.Assert(expectedParticles != null, "expectedParticles != null -- GetExpectedParticles should return empty at worst");
XElement element = node as XElement;
if (element != null)
{
if (!IsElementExpected(element, expectedParticles))
{
AppendWithCreation(ref unexpectedNodes, element);
}
else
{
this.ValidateElement(element);
expectedParticles = null;
}
}
else
{
XText text = node as XText;
if (text != null)
{
string s = text.Value;
if (s.Length > 0)
{
validator.ValidateText(s);
expectedParticles = null;
}
}
}
}
if (unexpectedNodes != null)
{
foreach (var node in unexpectedNodes)
{
node.Remove();
}
}
}
#endregion Private methods.
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Provides a class used to make an XElement conform to a given
// XML Schema.
//
//
// @owner [....]
//---------------------------------------------------------------------
namespace System.Data.Services.Design.Xml
{
#region Namespaces.
using System.Diagnostics;
using System;
using System.Linq;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Runtime.Versioning;
#endregion Namespaces.
/// Use this class to remove unexpected elements and attributes from an XDocument instance.
internal class XNodeSchemaApplier
{
#region Private fields.
/// Namespace manager for current scope.
private readonly XmlNamespaceManager namespaceManager;
/// Schemas used to predict expected elements and attributes.
private readonly XmlSchemaSet schemas;
/// XName for xsi:type.
private readonly XName xsiTypeName;
/// XName for xsi:nil.
private readonly XName xsiNilName;
/// Schema validator used to predict expected elements and attributes.
private XmlSchemaValidator validator;
#endregion Private fields.
#region Constructors.
/// Initializes a new instance.
/// Schemas to use to predict elements and attributes.
private XNodeSchemaApplier(XmlSchemaSet schemas)
{
Debug.Assert(schemas != null, "schemas != null");
this.schemas = schemas;
XNamespace xsi = XNamespace.Get("http://www.w3.org/2001/XMLSchema-instance");
this.xsiTypeName = xsi.GetName("type");
this.xsiNilName = xsi.GetName("nil");
this.namespaceManager = new XmlNamespaceManager(schemas.NameTable);
}
#endregion Constructors.
#region Internal methods.
///
/// Appends to the specified , creating as necessary.
///
/// List element type.
/// List to add the element to, possibly null on entry.
/// Element to add to the list.
internal static void AppendWithCreation(ref List list, T element)
{
if (list == null)
{
list = new List();
}
list.Add(element);
}
///
/// Applies the specified to remove unexpected elements and attributes from the
/// given .
///
/// Set of schemas to apply.
/// Document to remove elements and attributes from.
internal static void Apply(XmlSchemaSet schemas, XElement element)
{
Debug.Assert(schemas != null, "schemas != null");
Debug.Assert(element != null, "document != null");
XNodeSchemaApplier applier = new XNodeSchemaApplier(schemas);
applier.Validate(element);
}
#endregion Internal methods.
#region Private methods.
/// Determines whether the specified is expected.
/// Element to check.
///
/// of the (passed to avoid recreation).
///
/// Expected schema particle.
/// true if the element is expected; false otherwise.
private static bool IsElementExpected(XElement element, XmlQualifiedName elementName, XmlSchemaParticle expected)
{
Debug.Assert(element != null, "element != null");
Debug.Assert(elementName != null, "elementName != null");
Debug.Assert(expected != null, "expected != null");
Debug.Assert(
ToQualifiedName(element.Name) == elementName,
"ToQualifiedName(element.Name) == elementName -- otherwise the caller get the 'caching' wrong");
// These are all possibilities for a particle.
XmlSchemaGroupRef schemaGroupRef = expected as XmlSchemaGroupRef;
XmlSchemaAny schemaAny = expected as XmlSchemaAny;
XmlSchemaElement schemaElement = expected as XmlSchemaElement;
XmlSchemaAll schemaAll = expected as XmlSchemaAll;
XmlSchemaChoice schemaChoice = expected as XmlSchemaChoice;
XmlSchemaSequence schemaSequence = expected as XmlSchemaSequence;
Debug.Assert(schemaGroupRef == null, "schemaGroupRef == null -- the validator flattens this out as options.");
Debug.Assert(schemaSequence == null, "schemaSequence == null -- the validator flattens this out and picks the right one in seq.");
Debug.Assert(schemaAll == null, "schemaAll == null -- the validator flattens this out as options.");
Debug.Assert(schemaChoice == null, "schemaChoice == null -- the validator flattens this out as options.");
if (schemaAny != null)
{
Debug.Assert(
schemaAny.Namespace == "##other" || schemaAny.Namespace == "##any",
"schemaAny.Namespace == '##other' || '##any' -- otherwise CSDL XSD resource was changed");
if (schemaAny.Namespace == "##any")
{
return true;
}
else if (schemaAny.Namespace == "##other")
{
string realElementNamespace = element.Name.NamespaceName;
if (realElementNamespace != GetTargetNamespace(expected))
{
return true;
}
}
}
if (schemaElement != null)
{
if (schemaElement.QualifiedName == elementName)
{
return true;
}
}
return false;
}
/// Gets the target namespace that applies to the specified .
/// XML schema object for which to get target namespace.
/// Target namespace for the specified (never null).
private static string GetTargetNamespace(XmlSchemaObject schemaObject)
{
Debug.Assert(schemaObject != null, "schemaObject != null");
string result = null;
do
{
XmlSchema schema = schemaObject as XmlSchema;
if (schema != null)
{
result = schema.TargetNamespace;
Debug.Assert(!String.IsNullOrEmpty(schema.TargetNamespace), "schema.TargetNamespace != null||'' -- otherwise this isn't CSDL");
}
else
{
schemaObject = schemaObject.Parent;
Debug.Assert(schemaObject != null, "o != null -- otherwise the object isn't parented to a schema");
}
}
while (result == null);
return result;
}
/// Determines whether the specified is expected.
/// Element to check.
/// Expected schema particles (possibly empty).
/// true if the element is expected; false otherwise.
private static bool IsElementExpected(XElement element, XmlSchemaParticle[] expectedParticles)
{
Debug.Assert(element != null, "element != null");
Debug.Assert(expectedParticles != null, "expectedParticles != null");
XmlQualifiedName elementName = ToQualifiedName(element.Name);
foreach (var expected in expectedParticles)
{
if (IsElementExpected(element, elementName, expected))
{
return true;
}
}
return false;
}
/// Determines whether the specified is expected.
/// Attribute to check.
/// Expected attributes (possibly empty).
/// anyAttribute schema for a complex type element (possibly null).
/// true if the attribute is expected; false otherwise.
private static bool IsAttributeExpected(XAttribute attribute, XmlSchemaAnyAttribute anyAttribute, XmlSchemaAttribute[] expectedAttributes)
{
Debug.Assert(attribute != null, "attribute != null");
Debug.Assert(expectedAttributes != null, "expectedAttributes != null");
Debug.Assert(expectedAttributes.All(a => a.Form != XmlSchemaForm.Qualified), "expectedAttributes.All(a => a.Form != XmlSchemaForm.Qualified)");
var name = ToQualifiedName(attribute.Name);
if (name.Namespace.Length == 0)
{
foreach (var expected in expectedAttributes)
{
if (expected.Name == name.Name)
{
return true;
}
}
}
if (anyAttribute != null)
{
Debug.Assert(
anyAttribute.Namespace == "##any" || anyAttribute.Namespace == "##other",
"anyAttribute.Namespace == '##any' || '##other' -- otherwise CSDL XSD resource was changed");
if (anyAttribute.Namespace == "##any")
{
return true;
}
else
{
string attributeNamespace = attribute.Name.NamespaceName;
if (attributeNamespace.Length > 0 && attributeNamespace != GetTargetNamespace(anyAttribute))
{
return true;
}
}
}
return false;
}
///
/// Return the representation of the specified .
///
/// XML name to return.
/// An that represents the given .
private static XmlQualifiedName ToQualifiedName(XName name)
{
Debug.Assert(name != null, "name != null");
return new XmlQualifiedName(name.LocalName, name.NamespaceName);
}
/// Validates the specified object.
/// Source object for validation (must be an element).
private void Validate(XElement element)
{
Debug.Assert(element != null, "element != null");
XmlSchemaValidationFlags validationFlags = XmlSchemaValidationFlags.AllowXmlAttributes;
this.PushAncestorsAndSelf(element.Parent);
validator = new XmlSchemaValidator(schemas.NameTable, schemas, namespaceManager, validationFlags);
validator.XmlResolver = null;
validator.Initialize();
this.ValidateElement(element);
validator.EndValidation();
}
/// Pushes the specifed namespaces and those of ancestors.
/// Element to push from - possibly null.
///
/// Pushing in reverse order (up the tree rather than down the tree) is OK, because we check that
/// the namespace local name hasn't been added yet. Use as we go down
/// the tree to push/pop as usual.
///
private void PushAncestorsAndSelf(XElement element)
{
while (element != null)
{
foreach (XAttribute attribute in element.Attributes())
{
if (attribute.IsNamespaceDeclaration)
{
string localName = attribute.Name.LocalName;
if (localName == "xmlns")
{
localName = string.Empty;
}
if (!namespaceManager.HasNamespace(localName))
{
namespaceManager.AddNamespace(localName, attribute.Value);
}
}
}
element = element.Parent as XElement;
}
}
/// Pushes the specifed namespaces and those of ancestors.
/// Element to push.
/// The value for xsi:type on this element.
/// The value for xsi:nil on this element.
private void PushElement(XElement element, ref string xsiType, ref string xsiNil)
{
Debug.Assert(element != null, "e != null");
namespaceManager.PushScope();
foreach (XAttribute attribute in element.Attributes())
{
if (attribute.IsNamespaceDeclaration)
{
string localName = attribute.Name.LocalName;
if (localName == "xmlns")
{
localName = string.Empty;
}
namespaceManager.AddNamespace(localName, attribute.Value);
}
else
{
XName name = attribute.Name;
if (name == xsiTypeName)
{
xsiType = attribute.Value;
}
else if (name == xsiNilName)
{
xsiNil = attribute.Value;
}
}
}
}
/// Validates all attributes on the specified .
/// Element to validate attributes on.
private void ValidateAttributes(XElement element)
{
Debug.Assert(element != null, "e != null");
foreach (XAttribute attribute in element.Attributes())
{
if (!attribute.IsNamespaceDeclaration)
{
validator.ValidateAttribute(attribute.Name.LocalName, attribute.Name.NamespaceName, attribute.Value, null);
}
}
}
//// SxS: This method does not expose any resources to the caller and passes null as resource names to
//// XmlSchemaValidator.ValidateElement (annotated with ResourceExposure(ResourceScope.None).
//// It's OK to suppress the SxS warning.
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
[ResourceExposure(ResourceScope.None)]
private void ValidateElement(XElement e)
{
Debug.Assert(e != null, "e != null");
XmlSchemaInfo schemaInfo = new XmlSchemaInfo();
string xsiType = null;
string xsiNil = null;
this.PushElement(e, ref xsiType, ref xsiNil);
// The current element is always valid - otherwise we wouldn't have recursed into it in the first place.
validator.ValidateElement(e.Name.LocalName, e.Name.NamespaceName, schemaInfo, xsiType, xsiNil, null, null);
// When we have no schema element, then e was included but we don't know about it - it's an extension
// element, likely under CSDL documentation. We'll skip the whole thing in this case.
if (schemaInfo.SchemaElement != null)
{
XmlSchemaComplexType schemaComplexType = schemaInfo.SchemaElement.ElementSchemaType as XmlSchemaComplexType;
this.TrimAttributes(e, (schemaComplexType == null) ? null : schemaComplexType.AttributeWildcard);
this.ValidateAttributes(e);
validator.ValidateEndOfAttributes(null);
this.TrimAndValidateNodes(e);
}
validator.ValidateEndElement(null);
this.namespaceManager.PopScope();
}
/// Removes attributes from the specified if they're unexpected.
/// Element to remove attributes from.
/// anyAttribute schema for a complex type element (possibly null).
private void TrimAttributes(XElement element, XmlSchemaAnyAttribute anyAttribute)
{
Debug.Assert(element != null, "e != null");
List unexpectedAttributes = null;
var expectedAttributes = validator.GetExpectedAttributes();
foreach (XAttribute attribute in element.Attributes())
{
if (attribute.IsNamespaceDeclaration)
{
continue;
}
if (!IsAttributeExpected(attribute, anyAttribute, expectedAttributes))
{
AppendWithCreation(ref unexpectedAttributes, attribute);
}
}
if (unexpectedAttributes != null)
{
foreach (var attribute in unexpectedAttributes)
{
attribute.Remove();
}
}
}
///
/// Removes nodes from the specified element and validates its nodes.
///
///
///
/// While it's cleaner to do this in two passes, trim then validate, like we do with attributes, we need to
/// validate as we go for the validator to return sequence elements in the right order.
///
private void TrimAndValidateNodes(XElement parent)
{
Debug.Assert(parent != null, "parent != null");
List unexpectedNodes = null;
XmlSchemaParticle[] expectedParticles = null;
foreach (XNode node in parent.Nodes())
{
// expectedParticles will be null the first iteration and right after we validate,
// when we potentially have something different to validate against.
if (expectedParticles == null)
{
expectedParticles = validator.GetExpectedParticles();
}
Debug.Assert(expectedParticles != null, "expectedParticles != null -- GetExpectedParticles should return empty at worst");
XElement element = node as XElement;
if (element != null)
{
if (!IsElementExpected(element, expectedParticles))
{
AppendWithCreation(ref unexpectedNodes, element);
}
else
{
this.ValidateElement(element);
expectedParticles = null;
}
}
else
{
XText text = node as XText;
if (text != null)
{
string s = text.Value;
if (s.Length > 0)
{
validator.ValidateText(s);
expectedParticles = null;
}
}
}
}
if (unexpectedNodes != null)
{
foreach (var node in unexpectedNodes)
{
node.Remove();
}
}
}
#endregion Private methods.
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Selection.cs
- OutputWindow.cs
- DrawListViewSubItemEventArgs.cs
- JsonReaderDelegator.cs
- OrderPreservingSpoolingTask.cs
- OracleCommandBuilder.cs
- RectangleF.cs
- AsmxEndpointPickerExtension.cs
- QilPatternFactory.cs
- ColumnHeader.cs
- ThreadAbortException.cs
- AssemblyAssociatedContentFileAttribute.cs
- Int16KeyFrameCollection.cs
- NativeMethods.cs
- Delegate.cs
- ScriptMethodAttribute.cs
- SynchronousReceiveElement.cs
- Parameter.cs
- Cursors.cs
- XmlSchemaValidationException.cs
- UrlMapping.cs
- storepermissionattribute.cs
- BrushValueSerializer.cs
- WebScriptServiceHost.cs
- LinqDataSourceStatusEventArgs.cs
- SqlErrorCollection.cs
- RequestTimeoutManager.cs
- Annotation.cs
- XmlWrappingReader.cs
- HostedHttpTransportManager.cs
- BulletedListEventArgs.cs
- CryptoApi.cs
- CqlWriter.cs
- Panel.cs
- SslStream.cs
- Int64AnimationUsingKeyFrames.cs
- DiscoveryInnerClientManaged11.cs
- Decoder.cs
- TemplateParser.cs
- PropertyCollection.cs
- SchemaNotation.cs
- HashAlgorithm.cs
- XmlSchema.cs
- ScrollableControl.cs
- cache.cs
- CustomLineCap.cs
- FactoryId.cs
- ArithmeticException.cs
- AttachmentCollection.cs
- DateRangeEvent.cs
- XPathParser.cs
- PathFigureCollection.cs
- GrabHandleGlyph.cs
- UpdateTracker.cs
- HtmlValidatorAdapter.cs
- Int32RectValueSerializer.cs
- EncoderBestFitFallback.cs
- PointConverter.cs
- LocalizationParserHooks.cs
- LineMetrics.cs
- Debug.cs
- ComponentCollection.cs
- TabControl.cs
- LinkConverter.cs
- DynamicDocumentPaginator.cs
- DataRecord.cs
- XmlSchemaAttributeGroup.cs
- SubclassTypeValidatorAttribute.cs
- EmissiveMaterial.cs
- LoginUtil.cs
- SpellerHighlightLayer.cs
- NameValuePermission.cs
- InputReferenceExpression.cs
- GPRECTF.cs
- Int16KeyFrameCollection.cs
- EmptyStringExpandableObjectConverter.cs
- BitmapCacheBrush.cs
- Attribute.cs
- Freezable.cs
- BoundColumn.cs
- PartBasedPackageProperties.cs
- FrameDimension.cs
- AppSettingsReader.cs
- PathSegment.cs
- TerminatorSinks.cs
- UniqueEventHelper.cs
- X509Logo.cs
- StrokeNode.cs
- StrokeRenderer.cs
- InstanceDataCollection.cs
- _LocalDataStoreMgr.cs
- HttpCacheParams.cs
- ControlEvent.cs
- LambdaCompiler.cs
- ZipIOExtraFieldElement.cs
- CompModSwitches.cs
- Effect.cs
- XmlName.cs
- XmlNodeChangedEventArgs.cs
- ConnectionManagementElement.cs