如果您不希望使用基于XSLT的解决方案,那么您想要简洁,优雅和智能,就需要框架提供一些支持,特别是访问者模式可能会使这变得轻而易举。不幸的是,这里不可用。
我已经在LINQ的启发下实现了它ExpressionVisitor具有类似的结构。这样,您可以将访问者模式应用于(LINQ-to-)XML对象。(我对此进行了有限的测试,但据我所知,它运行良好)
public abstract class XObjectVisitor
{
    public virtual XObject Visit(XObject node)
    {
        if (node != null)
            return node.Accept(this);
        return node;
    }
    public ReadOnlyCollection<XObject> Visit(IEnumerable<XObject> nodes)
    {
        return nodes.Select(node => Visit(node))
            .Where(node => node != null)
            .ToList()
            .AsReadOnly();
    }
    public T VisitAndConvert<T>(T node) where T : XObject
    {
        if (node != null)
            return Visit(node) as T;
        return node;
    }
    public ReadOnlyCollection<T> VisitAndConvert<T>(IEnumerable<T> nodes) where T : XObject
    {
        return nodes.Select(node => VisitAndConvert(node))
            .Where(node => node != null)
            .ToList()
            .AsReadOnly();
    }
    protected virtual XObject VisitAttribute(XAttribute node)
    {
        return node.Update(node.Name, node.Value);
    }
    protected virtual XObject VisitComment(XComment node)
    {
        return node.Update(node.Value);
    }
    protected virtual XObject VisitDocument(XDocument node)
    {
        return node.Update(
            node.Declaration,
            VisitAndConvert(node.Nodes())
        );
    }
    protected virtual XObject VisitElement(XElement node)
    {
        return node.Update(
            node.Name,
            VisitAndConvert(node.Attributes()),
            VisitAndConvert(node.Nodes())
        );
    }
    protected virtual XObject VisitDocumentType(XDocumentType node)
    {
        return node.Update(
            node.Name,
            node.PublicId,
            node.SystemId,
            node.InternalSubset
        );
    }
    protected virtual XObject VisitProcessingInstruction(XProcessingInstruction node)
    {
        return node.Update(
            node.Target,
            node.Data
        );
    }
    protected virtual XObject VisitText(XText node)
    {
        return node.Update(node.Value);
    }
    protected virtual XObject VisitCData(XCData node)
    {
        return node.Update(node.Value);
    }
    #region Implementation details
    internal InternalAccessor Accessor
    {
        get { return new InternalAccessor(this); }
    }
    internal class InternalAccessor
    {
        private XObjectVisitor visitor;
        internal InternalAccessor(XObjectVisitor visitor) { this.visitor = visitor; }
        internal XObject VisitAttribute(XAttribute node) { return visitor.VisitAttribute(node); }
        internal XObject VisitComment(XComment node) { return visitor.VisitComment(node); }
        internal XObject VisitDocument(XDocument node) { return visitor.VisitDocument(node); }
        internal XObject VisitElement(XElement node) { return visitor.VisitElement(node); }
        internal XObject VisitDocumentType(XDocumentType node) { return visitor.VisitDocumentType(node); }
        internal XObject VisitProcessingInstruction(XProcessingInstruction node) { return visitor.VisitProcessingInstruction(node); }
        internal XObject VisitText(XText node) { return visitor.VisitText(node); }
        internal XObject VisitCData(XCData node) { return visitor.VisitCData(node); }
    }
    #endregion
}
public static class XObjectVisitorExtensions
{
    #region XObject.Accept "instance" method
    public static XObject Accept(this XObject node, XObjectVisitor visitor)
    {
        Validation.CheckNullReference(node);
        Validation.CheckArgumentNull(visitor, "visitor");
        // yay, easy dynamic dispatch
        Acceptor acceptor = new Acceptor(node as dynamic);
        return acceptor.Accept(visitor);
    }
    private class Acceptor
    {
        public Acceptor(XAttribute node) : this(v => v.Accessor.VisitAttribute(node)) { }
        public Acceptor(XComment node) : this(v => v.Accessor.VisitComment(node)) { }
        public Acceptor(XDocument node) : this(v => v.Accessor.VisitDocument(node)) { }
        public Acceptor(XElement node) : this(v => v.Accessor.VisitElement(node)) { }
        public Acceptor(XDocumentType node) : this(v => v.Accessor.VisitDocumentType(node)) { }
        public Acceptor(XProcessingInstruction node) : this(v => v.Accessor.VisitProcessingInstruction(node)) { }
        public Acceptor(XText node) : this(v => v.Accessor.VisitText(node)) { }
        public Acceptor(XCData node) : this(v => v.Accessor.VisitCData(node)) { }
        private Func<XObjectVisitor, XObject> accept;
        private Acceptor(Func<XObjectVisitor, XObject> accept) { this.accept = accept; }
        public XObject Accept(XObjectVisitor visitor) { return accept(visitor); }
    }
    #endregion
    #region XObject.Update "instance" method
    public static XObject Update(this XAttribute node, XName name, string value)
    {
        Validation.CheckNullReference(node);
        Validation.CheckArgumentNull(name, "name");
        Validation.CheckArgumentNull(value, "value");
        return new XAttribute(name, value);
    }
    public static XObject Update(this XComment node, string value = null)
    {
        Validation.CheckNullReference(node);
        return new XComment(value);
    }
    public static XObject Update(this XDocument node, XDeclaration declaration = null, params object[] content)
    {
        Validation.CheckNullReference(node);
        return new XDocument(declaration, content);
    }
    public static XObject Update(this XElement node, XName name, params object[] content)
    {
        Validation.CheckNullReference(node);
        Validation.CheckArgumentNull(name, "name");
        return new XElement(name, content);
    }
    public static XObject Update(this XDocumentType node, string name, string publicId = null, string systemId = null, string internalSubset = null)
    {
        Validation.CheckNullReference(node);
        Validation.CheckArgumentNull(name, "name");
        return new XDocumentType(name, publicId, systemId, internalSubset);
    }
    public static XObject Update(this XProcessingInstruction node, string target, string data)
    {
        Validation.CheckNullReference(node);
        Validation.CheckArgumentNull(target, "target");
        Validation.CheckArgumentNull(data, "data");
        return new XProcessingInstruction(target, data);
    }
    public static XObject Update(this XText node, string value = null)
    {
        Validation.CheckNullReference(node);
        return new XText(value);
    }
    public static XObject Update(this XCData node, string value = null)
    {
        Validation.CheckNullReference(node);
        return new XCData(value);
    }
    #endregion
}
public static class Validation
{
    public static void CheckNullReference<T>(T obj) where T : class
    {
        if (obj == null)
            throw new NullReferenceException();
    }
    public static void CheckArgumentNull<T>(T obj, string paramName) where T : class
    {
        if (obj == null)
            throw new ArgumentNullException(paramName);
    }
}
ps,此特定实现使用一些.NET 4功能使实现更容易/更简洁(使用dynamic和默认参数)。使其与.NET 3.5兼容,甚至与.NET 2.0兼容,应该不是很困难。
然后实现访问者,这是一个通用的访问者,可以更改多个名称空间(和使用的前缀)。
public class ChangeNamespaceVisitor : XObjectVisitor
{
    private INamespaceMappingManager manager;
    public ChangeNamespaceVisitor(INamespaceMappingManager manager)
    {
        Validation.CheckArgumentNull(manager, "manager");
        this.manager = manager;
    }
    protected INamespaceMappingManager Manager { get { return manager; } }
    private XName ChangeNamespace(XName name)
    {
        var mapping = Manager.GetMapping(name.Namespace);
        return mapping.ChangeNamespace(name);
    }
    private XObject ChangeNamespaceDeclaration(XAttribute node)
    {
        var mapping = Manager.GetMapping(node.Value);
        return mapping.ChangeNamespaceDeclaration(node);
    }
    protected override XObject VisitAttribute(XAttribute node)
    {
        if (node.IsNamespaceDeclaration)
            return ChangeNamespaceDeclaration(node);
        return node.Update(ChangeNamespace(node.Name), node.Value);
    }
    protected override XObject VisitElement(XElement node)
    {
        return node.Update(
            ChangeNamespace(node.Name),
            VisitAndConvert(node.Attributes()),
            VisitAndConvert(node.Nodes())
        );
    }
}
// and all the gory implementation details
public class NamespaceMappingManager : INamespaceMappingManager
{
    private Dictionary<XNamespace, INamespaceMapping> namespaces = new Dictionary<XNamespace, INamespaceMapping>();
    public NamespaceMappingManager Add(XNamespace fromNs, XNamespace toNs, string toPrefix = null)
    {
        var item = new NamespaceMapping(fromNs, toNs, toPrefix);
        namespaces.Add(item.FromNs, item);
        return this;
    }
    public INamespaceMapping GetMapping(XNamespace fromNs)
    {
        INamespaceMapping mapping;
        if (!namespaces.TryGetValue(fromNs, out mapping))
            mapping = new NullMapping();
        return mapping;
    }
    private class NullMapping : INamespaceMapping
    {
        public XName ChangeNamespace(XName name)
        {
            return name;
        }
        public XObject ChangeNamespaceDeclaration(XAttribute node)
        {
            return node.Update(node.Name, node.Value);
        }
    }
    private class NamespaceMapping : INamespaceMapping
    {
        private XNamespace fromNs;
        private XNamespace toNs;
        private string toPrefix;
        public NamespaceMapping(XNamespace fromNs, XNamespace toNs, string toPrefix = null)
        {
            this.fromNs = fromNs ?? "";
            this.toNs = toNs ?? "";
            this.toPrefix = toPrefix;
        }
        public XNamespace FromNs { get { return fromNs; } }
        public XNamespace ToNs { get { return toNs; } }
        public string ToPrefix { get { return toPrefix; } }
        public XName ChangeNamespace(XName name)
        {
            return name.Namespace == fromNs
                ? toNs + name.LocalName
                : name;
        }
        public XObject ChangeNamespaceDeclaration(XAttribute node)
        {
            if (node.Value == fromNs.NamespaceName)
            {
                if (toNs == XNamespace.None)
                    return null;
                var xmlns = !String.IsNullOrWhiteSpace(toPrefix)
                    ? (XNamespace.Xmlns + toPrefix)
                    : node.Name;
                return node.Update(xmlns, toNs.NamespaceName);
            }
            return node.Update(node.Name, node.Value);
        }
    }
}
public interface INamespaceMappingManager
{
    INamespaceMapping GetMapping(XNamespace fromNs);
}
public interface INamespaceMapping
{
    XName ChangeNamespace(XName name);
    XObject ChangeNamespaceDeclaration(XAttribute node);
}
还有一些辅助方法可以使球滚动:
T ChangeNamespace<T>(T node, XNamespace fromNs, XNamespace toNs, string toPrefix = null) where T : XObject
{
    return node.Accept(
        new ChangeNamespaceVisitor(
            new NamespaceMappingManager()
                .Add(fromNs, toNs, toPrefix)
        )
    ) as T;
}
然后要删除名称空间,可以这样命名:
var doc = ChangeNamespace(XDocument.Load(pathToXml),
    fromNs: "http://schema.peters.com/doc_353/1/Types",
    toNs: null);
使用此访问者,您可以编写一个INamespaceMappingManager来删除所有名称空间。
T RemoveAllNamespaces<T>(T node) where T : XObject
{
    return node.Accept(
        new ChangeNamespaceVisitor(new RemoveNamespaceMappingManager())
    ) as T;
}
public class RemoveNamespaceMappingManager : INamespaceMappingManager
{
    public INamespaceMapping GetMapping(XNamespace fromNs)
    {
        return new RemoveNamespaceMapping();
    }
    private class RemoveNamespaceMapping : INamespaceMapping
    {
        public XName ChangeNamespace(XName name)
        {
            return name.LocalName;
        }
        public XObject ChangeNamespaceDeclaration(XAttribute node)
        {
            return null;
        }
    }
}