【问题标题】:LINQ2XML Moving all namespace declarations to root elementLINQ2XML 将所有命名空间声明移动到根元素
【发布时间】:2013-07-10 02:17:23
【问题描述】:

这听起来像是很多人都会有的查询,但经过数小时的搜索,我什至找不到解决此问题的问题。

我正在使用 LINQ2Xml 类来生成 XML 文档。我正在使用许多命名空间,并且节点是动态创建的,因此不能使用新的 XElement("abc",new XElement...)) 格式声明。

这是一个例子:

XNamespace ns1 = "scheme://ns1";
XNamespace ns2 = "scheme://ns2";
XNamespace ns3 = "scheme://ns3";
XNamespace ns4 = "scheme://ns4";

XElement el1 = new XElement(ns1 + "el1");
XElement el2 = new XElement(ns2 + "el2");
XElement el3 = new XElement(ns3 + "el3");
XElement el4 = new XElement(ns4 + "el4");

XElement el5 = new XElement(ns1 + "el5");
XElement el6 = new XElement(ns1 + "el5");
XElement el7 = new XElement(ns1 + "el5");

el4.Add(el7);
el3.Add(el6);
el2.Add(el5);

el1.Add(el2);
el1.Add(el3);
el1.Add(el4);

XDocument doc = new XDocument(el1);
Debug.Write(doc.ToString());

以上代码产生以下输出:

<el1 xmlns="scheme://ns1">
  <el2 xmlns="scheme://ns2">
    <el5 xmlns="scheme://ns1" />
  </el2>
  <el3 xmlns="scheme://ns3">
    <el5 xmlns="scheme://ns1" />
  </el3>
  <el4 xmlns="scheme://ns4">
    <el5 xmlns="scheme://ns1" />
  </el4>
</el1>

然而,我希望输出更类似于以下 (E&OE),其中所有命名空间声明都位于顶部,而不是每个元素上。

<el1 xmlns="scheme://ns1" xmlns:ns2="scheme://ns2" xmlns:ns3="scheme://ns3" xmlns:ns4="scheme://ns4">
    <ns2:el2 >
        <ns1:el5 />
    </ns2:el2>
    ....
</el1>

我已经尝试了以下绝对没有区别的方法:

IEnumerable<XAttribute> allNs = doc.Root.Descendants().Attributes().Where(a => a.IsNamespaceDeclaration);
int i = 0;
foreach (string uri in allNs.Select(a => a.Value).Distinct()) {
    string prefix = "ns" + ++i;
    doc.Root.Add(new XAttribute(XNamespace.Xmlns + prefix, uri));
}
Debug.Write(doc.ToString(SaveOptions.OmitDuplicateNamespaces));

推理:我希望一个文件可能有多达几十个命名空间和每个命名空间的数百个元素。每个命名空间的 uri 可能有 50 个字符长,我将通过只声明命名空间一次来节省数千个字符。此外,它只是看起来更好!

有人知道这是怎么做到的吗?

【问题讨论】:

    标签: c# xml namespaces xml-namespaces xelement


    【解决方案1】:

    将其他命名空间作为属性添加到根元素:

    XElement el1 = new XElement(ns1 + "el1", 
        new XAttribute(XNamespace.Xmlns + "ns2", ns2),
        new XAttribute(XNamespace.Xmlns + "ns3", ns3),
        new XAttribute(XNamespace.Xmlns + "ns4", ns4));
    

    输出:

    <el1 xmlns:ns2="scheme://ns2" xmlns:ns3="scheme://ns3" xmlns:ns4="scheme://ns4" xmlns="scheme://ns1">
      <ns2:el2>
        <el5 />
      </ns2:el2>
      <ns3:el3>
        <el5 />
      </ns3:el3>
      <ns4:el4>
        <el5 />
      </ns4:el4>
    </el1>
    

    【讨论】:

    • 谢谢,我以为这就是我在最后一个代码块中所做的。事实证明,在序列化之前不会创建 xmlns 属性。这是我最终使用的代码(我忘了提,我在编译时不知道所有的命名空间): IEnumerable allNs = doc.Descendants().Select(e => e.Name.Namespace) 。清楚的();诠释 i = 0; foreach (XNamespace ns in allNs) { string prefix = "ns" + ++i; doc.Root.Add(new XAttribute(XNamespace.Xmlns + prefix, ns)); }
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-30
    • 2014-04-24
    • 2012-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多