将XML名称空间浮动到根
本文关键字:空间 XML | 更新日期: 2023-09-27 18:02:47
我在c#程序中有一个XML,看起来像这样:
<el1 xmlns="http://URI1">
<el2 xmlns:namespace2="http://URI2"></el2>
<el3>
<el4 xmlns:namespace3="http://URI3"></el4>
</el3>
</el1>
为了整洁,我想把所有的命名空间声明移到根元素中。我无法更改生成此XML的导出,因此需要一个解决方案来处理上面所示的示例。实现这一目标的好方法是什么?
为简洁起见,本例被简化了,但假设有更多的子元素实际使用这些前缀。这些与这个问题无关,因为所有命名空间前缀声明都是唯一的,我的目标只是将它们移动到树的更高位置。
我已经查看了XML的MSDN文档,但是似乎没有像这样操作名称空间的简单方法。我尝试过的解决方案之一是作为XElement与XML交互,并基于XAttribute收集名称空间。IsNamespaceDeclaration,用其本地名称替换每个元素,最后用收集到的名称空间XAttributes列表创建一个新的根元素。然而,这一系列的实验导致了一堆关于重新定义前缀的错误,我不确定我是否在正确的方向上移动。
你需要添加一个前缀
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
{
}
}
您可以使用namespace
xpath轴定位所有xml属性。将这些属性添加到根元素。最后,使用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);
}