| File: InternalUtilities\XmlUtilities.cs | Web Access |
| Project: src\roslyn\src\Compilers\Core\Portable\Microsoft.CodeAnalysis.csproj (Microsoft.CodeAnalysis) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Xml; using System.Xml.Linq; namespace Roslyn.Utilities { internal static class XmlUtilities { internal static TNode Copy<TNode>(this TNode node, bool copyAttributeAnnotations) where TNode : XNode { XNode copy; // Documents can't be added to containers, so our usual copy trick won't work. if (node.NodeType == XmlNodeType.Document) { copy = new XDocument(((XDocument)(object)node)); } else { XContainer temp = new XElement("temp"); temp.Add(node); copy = temp.LastNode!; temp.RemoveNodes(); } Debug.Assert(copy != node); Debug.Assert(copy.Parent == null); // Otherwise, when we give it one, it will be copied. // Copy annotations, the above doesn't preserve them. // We need to preserve Location annotations as well as line position annotations. CopyAnnotations(node, copy); // We also need to preserve line position annotations for all attributes // since we report errors with attribute locations. if (copyAttributeAnnotations && node.NodeType == XmlNodeType.Element) { var sourceElement = ((XElement)(object)node); var targetElement = ((XElement)copy); IEnumerator<XAttribute> sourceAttributes = sourceElement.Attributes().GetEnumerator(); IEnumerator<XAttribute> targetAttributes = targetElement.Attributes().GetEnumerator(); while (sourceAttributes.MoveNext() && targetAttributes.MoveNext()) { Debug.Assert(sourceAttributes.Current.Name == targetAttributes.Current.Name); CopyAnnotations(sourceAttributes.Current, targetAttributes.Current); } } return (TNode)copy; } private static void CopyAnnotations(XObject source, XObject target) { foreach (var annotation in source.Annotations<object>()) { target.AddAnnotation(annotation); } } internal static XElement[]? TrySelectElements(XNode node, string xpath, out string? errorMessage, out bool invalidXPath) { errorMessage = null; invalidXPath = false; try { var xpathResult = System.Xml.XPath.Extensions.XPathSelectElements(node, xpath); // Throws InvalidOperationException if the result of the XPath is an XDocument: return xpathResult?.ToArray(); } catch (InvalidOperationException e) { errorMessage = e.Message; return null; } catch (Exception e) when (e.GetType().FullName == "System.Xml.XPath.XPathException") { errorMessage = e.Message; invalidXPath = true; return null; } } } }