使用带有 System.Xml.Linq 的 XElement 将不同的 xml 命名空间重新定义为现有别名时出错
Error when redefining a different xml Namespace to an existing alias using XElement with System.Xml.Linq
我尝试将以下 xml 文档(简化版)编程为代码:
<P xmlns="http://schemas.microsoft.com/x/2010/manifest"
xmlns:ab="http://schemas.microsoft.com/a/2010/manifest"
xmlns:ac="http://schemas.microsoft.com/a/2013/manifest">
<ab:Ex xmlns:ab="http://schemas.microsoft.com/a/2013/manifest">
</ab:Ex>
</P>
现在一个元素重新定义了命名空间:
xmlns:ab="http://schemas.microsoft.com/a/2013/manifest".
如何将元素添加到我的程序中?这显然是有效的,因为我可以像这样加载 xml 文件:
Add(new XAttribute (XNamespace.Xmlns + "ab")
我收到错误消息:
System.Xml.XmlException: 'The prefix 'ab' cannot be redefined from 'http://schemas.microsoft.com/a/2010/manifest' to 'http://schemas.microsoft.com/a/2013/manifest' within the same start element tag.'
实际上合乎逻辑(重新定义)但是当我加载文档时,该元素被接受了。
using System.Xml.Linq;
namespace xmltest
{
class Program
{
static void Main(string[] args)
{
//Load
XDocument doc1 = XDocument.Load(@"c:\simple.xml", LoadOptions.None);
System.Console.WriteLine(doc1.ToString());
//Create new
XNamespace ab = "http://schemas.microsoft.com/a/2010/manifest";
XNamespace nsx = "http://schemas.microsoft.com/x/2010/manifest";
XDocument doc2 = new XDocument(new XDeclaration("1.0", "utf-8", ""),
new XElement(nsx + "P"));
doc2.Element(nsx + "P").Add(new XAttribute("xmlns",
"http://schemas.microsoft.com/x/2010/manifest"));
doc2.Element(nsx + "P").Add(new XAttribute(XNamespace.Xmlns + "ab",
"http://schemas.microsoft.com/a/2010/manifest"));
doc2.Element(nsx + "P").Add(new XAttribute(XNamespace.Xmlns + "ac",
"http://schemas.microsoft.com/a/2013/manifest"));
XElement xml = new XElement(ab + "Ex");
//--> Below does not work work
xml.Add(new XAttribute(XNamespace.Xmlns + "ab",
"http://schemas.microsoft.com/a/2013/manifest"));
doc2.Element(nsx + "P").Add(xml);
System.Console.WriteLine(doc2.ToString());
}
}
}
有人知道如何解决这个问题吗?
理论上,因为
<ab:Ex xmlns:ab="http://schemas.microsoft.com/a/2013/manifest">
其实就是要在new命名空间(2013)中定义Ex,你可以通过在新的命名空间中定义Ex来得到你想要的,即:
XNamespace abOld = "http://schemas.microsoft.com/a/2010/manifest";
XNamespace abNew = "http://schemas.microsoft.com/a/2013/manifest";
XNamespace nsx = ...
XElement xml = new XElement(abNew + "Ex");
xml.Add(new XAttribute(XNamespace.Xmlns + "ab",
"http://schemas.microsoft.com/a/2013/manifest"));
但是,重新利用现有命名空间的别名只是为了让您可以使用相同的别名对于未来的维护来说真的很混乱 - 当别名离开范围时,它将恢复到它的旧定义。我建议您至少为 2010 和 2013 命名空间创建不同的、唯一的别名。
此外,除非 Xml 的预期使用者有问题,并且需要特定的别名或命名空间范围,否则我通常会避免对命名空间别名和命名空间范围进行微观管理 - 让 Linq 到 Xml 为你管理。
例如,如何:
XNamespace abOld = "http://schemas.microsoft.com/a/2010/manifest";
XNamespace abNew = "http://schemas.microsoft.com/a/2013/manifest";
// Build up the document by providing element, attribute + applicable namespaces:
var root = new XElement(abOld + "P",
new XElement(abNew + "Ex"));
我尝试将以下 xml 文档(简化版)编程为代码:
<P xmlns="http://schemas.microsoft.com/x/2010/manifest"
xmlns:ab="http://schemas.microsoft.com/a/2010/manifest"
xmlns:ac="http://schemas.microsoft.com/a/2013/manifest">
<ab:Ex xmlns:ab="http://schemas.microsoft.com/a/2013/manifest">
</ab:Ex>
</P>
现在一个元素重新定义了命名空间:
xmlns:ab="http://schemas.microsoft.com/a/2013/manifest".
如何将元素添加到我的程序中?这显然是有效的,因为我可以像这样加载 xml 文件:
Add(new XAttribute (XNamespace.Xmlns + "ab")
我收到错误消息:
System.Xml.XmlException: 'The prefix 'ab' cannot be redefined from 'http://schemas.microsoft.com/a/2010/manifest' to 'http://schemas.microsoft.com/a/2013/manifest' within the same start element tag.'
实际上合乎逻辑(重新定义)但是当我加载文档时,该元素被接受了。
using System.Xml.Linq;
namespace xmltest
{
class Program
{
static void Main(string[] args)
{
//Load
XDocument doc1 = XDocument.Load(@"c:\simple.xml", LoadOptions.None);
System.Console.WriteLine(doc1.ToString());
//Create new
XNamespace ab = "http://schemas.microsoft.com/a/2010/manifest";
XNamespace nsx = "http://schemas.microsoft.com/x/2010/manifest";
XDocument doc2 = new XDocument(new XDeclaration("1.0", "utf-8", ""),
new XElement(nsx + "P"));
doc2.Element(nsx + "P").Add(new XAttribute("xmlns",
"http://schemas.microsoft.com/x/2010/manifest"));
doc2.Element(nsx + "P").Add(new XAttribute(XNamespace.Xmlns + "ab",
"http://schemas.microsoft.com/a/2010/manifest"));
doc2.Element(nsx + "P").Add(new XAttribute(XNamespace.Xmlns + "ac",
"http://schemas.microsoft.com/a/2013/manifest"));
XElement xml = new XElement(ab + "Ex");
//--> Below does not work work
xml.Add(new XAttribute(XNamespace.Xmlns + "ab",
"http://schemas.microsoft.com/a/2013/manifest"));
doc2.Element(nsx + "P").Add(xml);
System.Console.WriteLine(doc2.ToString());
}
}
}
有人知道如何解决这个问题吗?
理论上,因为
<ab:Ex xmlns:ab="http://schemas.microsoft.com/a/2013/manifest">
其实就是要在new命名空间(2013)中定义Ex,你可以通过在新的命名空间中定义Ex来得到你想要的,即:
XNamespace abOld = "http://schemas.microsoft.com/a/2010/manifest";
XNamespace abNew = "http://schemas.microsoft.com/a/2013/manifest";
XNamespace nsx = ...
XElement xml = new XElement(abNew + "Ex");
xml.Add(new XAttribute(XNamespace.Xmlns + "ab",
"http://schemas.microsoft.com/a/2013/manifest"));
但是,重新利用现有命名空间的别名只是为了让您可以使用相同的别名对于未来的维护来说真的很混乱 - 当别名离开范围时,它将恢复到它的旧定义。我建议您至少为 2010 和 2013 命名空间创建不同的、唯一的别名。
此外,除非 Xml 的预期使用者有问题,并且需要特定的别名或命名空间范围,否则我通常会避免对命名空间别名和命名空间范围进行微观管理 - 让 Linq 到 Xml 为你管理。
例如,如何:
XNamespace abOld = "http://schemas.microsoft.com/a/2010/manifest";
XNamespace abNew = "http://schemas.microsoft.com/a/2013/manifest";
// Build up the document by providing element, attribute + applicable namespaces:
var root = new XElement(abOld + "P",
new XElement(abNew + "Ex"));