【问题标题】:Float XML Namespaces to Root?将 XML 命名空间浮动到根目录?
【发布时间】:2015-10-04 21:04:04
【问题描述】:

我在一个 C# 程序中有 XML,看起来像这样:

<el1 xmlns="http://URI1">
    <el2 xmlns:namespace2="http://URI2"></el2>
    <el3>
        <el4 xmlns:namespace3="http://URI3"></el4>
    </el3>
</el1>

为了整洁,我想将所有命名空间声明移至根元素。我无法更改生成此 XML 的导出,因此需要对示例进行解决方案,如上所示。有什么好的方法可以做到这一点?

为了简洁起见,这个例子被简化了,但假设还有更多的子元素实际使用这些前缀。这些与这个问题无关,因为所有命名空间前缀声明都是唯一的,我的目标只是将它们移到树中更高的位置。

我已经查看了 XML 的 MSDN 文档,但似乎没有像这样操作命名空间的简单方法。我尝试过的解决方案之一是将 XML 作为 XElement 进行交互并基于 XAttribute.IsNamespaceDeclaration 收集命名空间,将每个元素替换为其本地名称,最后使用收集的命名空间 XAttributes 列表创建一个新的根元素。不过,这一系列实验导致了一系列关于重新定义前缀的错误,我不确定我是否朝着正确的方向前进。

【问题讨论】:

  • 为了整洁,我想将所有命名空间声明移动到根元素...我不确定我是否朝着正确的方向前进 在根元素上声明前缀没有什么更清楚的。追求这个目标没有正确的方向。
  • 对不起,我想我不是很清楚。这不仅仅是为了美观,我最终需要将它传递给一个 Web 服务,无论出于何种原因,它都需要在根元素中声明的命名空间。我所描述的目标是我的上下文中的必要目标。
  • 那么web服务就坏了。正确的方向是坚持他们修复它。

标签: c# asp.net xml namespaces


【解决方案1】:

你需要添加前缀

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace ConsoleApplication2
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            El1 el1 = new El1()
            {
                el2 = new El2()
                {
                    el3 = new El3() {
                        el4 = new El4() {
                        }

                    }
                }
            };

            XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
            ns.Add("u4", "http://URI4");
            ns.Add("u3", "http://URI3");
            ns.Add("u2", "http://URI2");
            ns.Add("", "http://URI1");

            XmlSerializer serializer = new XmlSerializer(typeof(El1));

            StreamWriter writer = new StreamWriter(FILENAME);
            serializer.Serialize(writer, el1, ns);
            writer.Flush();
            writer.Close();
            writer.Dispose();

        }
    }

    [XmlRoot("el1", Namespace = "http://URI1")]
    public class El1
    {
        [XmlElement("el2", Namespace = "http://URI2")]
        public El2 el2 { get; set; }
    }
    [XmlRoot("el2")]
    public class El2
    {
        [XmlElement("el3", Namespace = "http://URI3")]
        public El3 el3 { get; set; }
    }
    [XmlRoot("el3", Namespace = "http://URI3")]
    public class El3
    {
        [XmlElement("el4", Namespace = "http://URI4")]
        public El4 el4 { get; set; }
    }
    [XmlRoot("el4", Namespace = "http://URI1")]
    public class El4
    {
    }
}
​

【讨论】:

    【解决方案2】:

    您可以使用namespace xpath 轴定位所有 xmls 属性。将这些属性添加到根元素。最后使用NamespaceHandling.OmitDuplicates 写出xml,这会将命名空间声明留在根目录中,并将它们从所有其他元素中删除。

    var xml = new XmlDocument();
    xml.Load("XMLFile1.xml");
    
    // Find all xmlns: attributes
    var attributes = xml.DocumentElement.SelectNodes("//namespace::*");
    
    // Add xmlns: attributes to the root
    foreach (XmlAttribute attribute in attributes)
        xml.DocumentElement.SetAttribute(attribute.Name, attribute.Value);
    
    // Write out results, ignoring duplicate xmlns: attributes
    var settings = new XmlWriterSettings();
    settings.NamespaceHandling = NamespaceHandling.OmitDuplicates;
    settings.Indent = true;
    
    using (var writer = XmlWriter.Create("XMLFile2.xml", settings))
    {
        xml.Save(writer);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-08
      • 2012-02-21
      • 1970-01-01
      • 1970-01-01
      • 2012-09-20
      • 1970-01-01
      相关资源
      最近更新 更多