【问题标题】:How do I create an XElement that contains a prefix without a wrapper?如何创建包含前缀但没有包装器的 XElement?
【发布时间】:2019-02-26 13:59:04
【问题描述】:

我正在尝试像这样创建一个简单的空 XElement:

<dyn:Positions>
   <Vector2-Array>
   </Vector2-Array>
</dyn:Positions>

我有上面定义的命名空间:

XNamespace dyn = "https://www.abc.at/dyn";

但是当我创建 XElement 时:

XElement positions = new XElement(dyn + "Positions", new XElement("Vector2-Array"));

结果是这样的:

<Positions xmlns="dyn">
  <Vector2-Array xmlns="" />
</Positions>

如果不将其包装在另一个 XElement 中,这可能吗?因为我需要这个元素稍后附加到另一个文档中,在里面添加更多元素之后。

【问题讨论】:

标签: c# xml xelement


【解决方案1】:

我认为您希望 Vector2-Array 与 Positions 位于 same 命名空间中,然后您在输出中看不到它:

XElement positions = new XElement(dyn + "Positions", 
       new XElement(dyn + "Vector2-Array"));

这给了

<Positions xmlns="https://www.abc.at/dyn">
  <Vector2-Array />
</Positions>

dyn: 表示法只是一种简写,以后在某些父 XML 中合并它时应该没有关系。您应该非常确定所有内容属于哪个命名空间。

【讨论】:

    【解决方案2】:

    因为您没有添加命名空间声明,所以 dyn 命名空间成为默认命名空间。

    然后,当您添加没有命名空间的子元素时,必须添加一个没有命名空间的命名空间声明,以表明它不在默认命名空间内。

    如果您的 dyn 命名空间不是默认命名空间,请尝试以下代码:

    XNamespace dyn = "https://www.abc.at/dyn";
    
    XElement positions = new XElement(
        dyn + "Positions",
        new XAttribute(XNamespace.Xmlns + "dyn", "https://www.abc.at/dyn"),
    new XElement("Vector2-Array"));
    

    这会产生以下输出:

    <dyn:Positions xmlns:dyn="https://www.abc.at/dyn">
      <Vector2-Array />
    </dyn:Positions>
    

    请注意,当您开始将此元素附加到其他文档时,如果命名空间有任何不匹配,您可能会得到更多类似于原始问题的行为。

    OP 专门提出了将这个元素附加到另一个也包含命名空间声明的元素的主题。

    我创建了这段代码来测试:

            XNamespace dyn = "https://www.abc.at/dyn";
    
            XElement positions = new XElement(
                dyn + "Positions",
                new XAttribute(XNamespace.Xmlns + "dyn", "https://www.abc.at/dyn"),
            new XElement("Vector2-Array"));
    
            XElement root = new XElement(
                dyn + "root",
                new XAttribute(XNamespace.Xmlns + "dyn", "https://www.abc.at/dyn"));
    
            root.Add(positions);
    

    使用调试器时,添加Positionsroot元素的XML是这样的:

    <dyn:root xmlns:dyn="https://www.abc.at/dyn">
      <dyn:Positions xmlns:dyn="https://www.abc.at/dyn">
        <Vector2-Array />
      </dyn:Positions>
    </dyn:root>
    

    所以命名空间声明是重复的。

    但是,当将 XML 保存或格式化为字符串时,可以使用 SaveOptionOmitDuplicateNamespaces

    Console.WriteLine(root.ToString(SaveOptions.OmitDuplicateNamespaces));
    

    结果输出如下:

    <dyn:root xmlns:dyn="https://www.abc.at/dyn">
      <dyn:Positions>
        <Vector2-Array />
      </dyn:Positions>
    </dyn:root>
    

    因为重复的命名空间声明实际上什么都不做(即使它们很丑陋),如果 XML 的显示很重要,那么可以通过这种方式删除它们。

    从功能上讲,只要它们匹配,重复的命名空间声明实际上不会做任何事情。

    【讨论】:

    • 有没有办法不将命名空间声明添加到新的 XElement 中?将添加“位置”的容器包含命名空间声明。我只需要新的 XElement 具有像“dyn:Positions”这样的前缀
    • 如果您自己创建一个 XElement,那么您要么需要添加命名空间声明,要么将其保留为默认命名空间,如 Henk Holterman 的回答更多。你不能创建一个独立的 XElement 并在没有命名空间声明的情况下拥有命名空间前缀。
    • 这意味着即使我有这个带有命名空间声明的单个 XElement,当我最终将它附加到也声明了命名空间的根时,它看起来就像我期望的那样带有前缀它?我会测试这个
    • @greenfeet 我刚刚做了一个测试,不幸的是附加的元素仍然有命名空间声明。我正在想办法解决这个问题 - 但如果您首先将 Positions 元素创建为独立元素,并且您希望它具有 dyn 前缀,那么您必须声明 dyn 命名空间.
    • @greenfeet 发现有一个保存选项可以删除重复的命名空间声明,如果有帮助的话。
    猜你喜欢
    • 1970-01-01
    • 2015-06-15
    • 2012-02-19
    • 1970-01-01
    • 1970-01-01
    • 2018-01-19
    • 1970-01-01
    • 1970-01-01
    • 2014-02-08
    相关资源
    最近更新 更多