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
- SqlConnectionFactory.cs
- CodeExpressionCollection.cs
- ScrollChangedEventArgs.cs
- DataGridViewColumnStateChangedEventArgs.cs
- UITypeEditors.cs
- DataPagerFieldCommandEventArgs.cs
- DeferredReference.cs
- SimpleHandlerBuildProvider.cs
- ToolConsole.cs
- SystemNetHelpers.cs
- WebPartConnectionsCancelVerb.cs
- PassportIdentity.cs
- RecommendedAsConfigurableAttribute.cs
- WebPartMovingEventArgs.cs
- WrapPanel.cs
- SiteMapDataSourceView.cs
- ImageDrawing.cs
- ObjectDataSourceSelectingEventArgs.cs
- GrammarBuilderRuleRef.cs
- FormatStringEditor.cs
- FullTextState.cs
- DataService.cs
- FreezableOperations.cs
- SymLanguageVendor.cs
- SiteMembershipCondition.cs
- EventToken.cs
- TablePattern.cs
- MD5.cs
- Transform.cs
- Error.cs
- AppDomainManager.cs
- ImageListUtils.cs
- WindowAutomationPeer.cs
- PermissionSet.cs
- SqlConnectionString.cs
- BindStream.cs
- NamespaceQuery.cs
- BinaryParser.cs
- FixedSOMFixedBlock.cs
- DocumentSequence.cs
- GacUtil.cs
- WebHttpBindingCollectionElement.cs
- MSG.cs
- OleStrCAMarshaler.cs
- IPHostEntry.cs
- Mappings.cs
- DataTransferEventArgs.cs
- ImmutableClientRuntime.cs
- CssStyleCollection.cs
- QilDataSource.cs
- PointAnimation.cs
- IFormattable.cs
- HttpDictionary.cs
- ExceptionRoutedEventArgs.cs
- ExpressionBindings.cs
- XmlSchemaExporter.cs
- TextServicesContext.cs
- ProfileGroupSettings.cs
- ResourceContainer.cs
- FactoryGenerator.cs
- SamlAudienceRestrictionCondition.cs
- SystemWebCachingSectionGroup.cs
- IISUnsafeMethods.cs
- MethodBuilderInstantiation.cs
- EventDriven.cs
- TreeIterator.cs
- TextSelection.cs
- EventArgs.cs
- DockPattern.cs
- ConversionValidationRule.cs
- DataErrorValidationRule.cs
- ExternalException.cs
- DockEditor.cs
- WebPartConnectionsDisconnectVerb.cs
- StaticResourceExtension.cs
- MemoryPressure.cs
- ExpressionNormalizer.cs
- OperationAbortedException.cs
- LinqDataSourceInsertEventArgs.cs
- SmtpException.cs
- XamlFrame.cs
- RequestCachePolicyConverter.cs
- CacheDependency.cs
- SoapFaultCodes.cs
- InputMethod.cs
- XmlDocumentFieldSchema.cs
- LinkUtilities.cs
- Funcletizer.cs
- IPAddressCollection.cs
- DataServiceConfiguration.cs
- ProjectionPlanCompiler.cs
- SiteMembershipCondition.cs
- AnnotationResource.cs
- UInt32Storage.cs
- TextBoxAutomationPeer.cs
- BasicAsyncResult.cs
- TouchDevice.cs
- DefaultSerializationProviderAttribute.cs
- AdornerDecorator.cs
- PerfService.cs