/// <summary> /// Given the specified element in a given namespace, remaps it into a /// <paramref name="targetNamespace"/> and trims elements and attributes that /// don't conform to the schema. /// </summary> /// <param name="element">Element to fit.</param> /// <param name="schemaNamespace">Namespace of element.</param> /// <param name="targetNamespace">Target namespace.</param> /// <returns>A new <see cref="XElement"/> that fits the specified <paramref name="targetNamespace"/>.</returns> private static XElement FitElementToSchema(XElement element, string schemaNamespace, string targetNamespace) { Debug.Assert(element != null, "element != null"); Debug.Assert(schemaNamespace != null, "schemaNamespace != null"); Debug.Assert(targetNamespace != null, "targetNamespace != null"); Debug.Assert( targetNamespace == XmlConstants.EdmV1dot1Namespace, "targetNamespace == XmlConstants.EdmV1dot1Namespace -- otherwise update CreateTargetSchemaSet to pull other schemas"); XmlSchemaSet schemas = CreateTargetSchemaSet(); XElement result = UpdateNamespaces(element, schemaNamespace, targetNamespace); XNodeSchemaApplier.Apply(schemas, result); return(result); }
/// <summary> /// Updates the namespaces under the specified <paramref name="element"/>, changing <paramref name="oldNamespaceName"/> /// into <paramref name="newNamespaceName"/>. /// </summary> /// <param name="element">Element to update (recursively).</param> /// <param name="oldNamespaceName">Old namespace.</param> /// <param name="newNamespaceName">New namespace.</param> /// <returns>The updated element.</returns> /// <remarks> /// Currently, the updates are in-place, so the returned element is always <paramref name="element"/>. /// /// For valid cases, there will be no qualified CSDL attributes, so those code paths are /// not likely to hit - however the code preserves the namespaces so it can fail /// correctly later on. /// </remarks> private static XElement UpdateNamespaces(XElement element, string oldNamespaceName, string newNamespaceName) { Debug.Assert(element != null, "element != null"); Debug.Assert(oldNamespaceName != null, "oldNamespaceName != null"); Debug.Assert(newNamespaceName != null, "newNamespaceName != null"); XNamespace oldNamespace = XNamespace.Get(oldNamespaceName); XNamespace newNamespace = XNamespace.Get(newNamespaceName); Stack <XElement> pending = new Stack <XElement>(); pending.Push(element); do { XElement e = pending.Pop(); if (e.Name.Namespace == oldNamespace) { e.Name = newNamespace.GetName(e.Name.LocalName); } List <XAttribute> attributesToReplace = null; foreach (XAttribute attribute in e.Attributes()) { if (attribute.IsNamespaceDeclaration) { if (attribute.Value == oldNamespaceName) { attribute.Value = newNamespaceName; } } else if (attribute.Name.Namespace == oldNamespace || IsOpenTypeAttribute(attribute)) { XNodeSchemaApplier.AppendWithCreation(ref attributesToReplace, attribute); } } if (attributesToReplace != null) { attributesToReplace.Remove(); foreach (XAttribute attribute in attributesToReplace) { if (IsOpenTypeAttribute(attribute)) { XAttribute existingAttribute = e.Attributes().SingleOrDefault(a => a.Name.NamespaceName == XmlConstants.EdmV1dot2Namespace && a.Name.LocalName == attribute.Name.LocalName); if (existingAttribute == null) { e.Add(new XAttribute(XNamespace.Get(XmlConstants.EdmV1dot2Namespace) + attribute.Name.LocalName, attribute.Value)); } else { existingAttribute.Value = attribute.Value; } } else { e.Add(new XAttribute(newNamespace.GetName(attribute.Name.LocalName), attribute.Value)); } } } foreach (var child in e.Elements()) { pending.Push(child); } }while (pending.Count > 0); return(element); }