【问题标题】:xml element name with colon带有冒号的 xml 元素名称
【发布时间】:2010-12-20 00:29:45
【问题描述】:

我正在使用第 3 方 xml api。他们已经定义了一个类似于下面的所需的 xml 结构。

<ns1:E xmlns:ns1="schema">
<ns1:B>
    <ns2:S>
        <ns2:V>
            <ns2:Bl />
        </ns2:V>
    </ns2:S>
</ns1:B>
</ns1:E>

有一个 SQL 表,其中包含我需要放入此 xml 格式的信息。我有一个 LINQ to SQL 适配器来获取数据,我正在使用 System.Xml 创建一个 XML 文档。

XmlDocument.CreateElement("ns1:E"); etc

只要我从元素名称中删除冒号,它就可以正常工作。对于冒号,只有冒号的右侧位于元素名称中。我知道冒号是一个禁忌,但我无法控制 3rd 方 api 所指示的内容。

我有哪些解决方法?是否有任何有用的方法可以将冒号强制输入元素名称?我不必使用XMLDocument,但不确定还有什么其他方法可以让我到达那里。

更新:我意识到&lt;ns1: 指的是一个命名空间。是的,有 2 个。在写出 XML 时,如果我说,我可以让它工作 -

 XmlDocument.CreateElement("ns1:E", "http://schema");

然而,这个的 XML 输出是

<ns1:E xmlns:ns1="http://schema">

如果我只是说XmlDocument.CreateElement("ns1:E"); 没有uri,那么输出就是&lt;E&gt;。我不希望输出具有架构引用,但我确实需要具有前缀。我想要达到的结果就是&lt;ns1:E&gt;。两个命名空间都在顶部声明,我认为这意味着我必须在每个节点上声明它们。

【问题讨论】:

    标签: .net xml namespaces linq-to-xml


    【解决方案1】:

    好的,就是这样。

    XmlDocument.CreateElement("prefix", "name", "uri");
    

    如果对其他人有帮助,请在此处参考:http://msdn.microsoft.com/en-us/library/c22k3d47.aspx1

    【讨论】:

    • 我遇到了同样的问题,即使这种方法对我也不起作用。你是如何简单地实现 的?
    【解决方案2】:

    冒号表示这些元素在 ns1 namespace 中。当您使用多个模式时,这是需要的。假设文档只使用 ns1,它本质上等同于在这些标签中没有任何“ns1:”。请参阅this guide 了解更多信息。

    【讨论】:

    • 实际上,那些冒号表示元素在schema命名空间中。 ns1 不是命名空间;它是命名空间的缩写。它可以改变;命名空间的名称不能 - 除非成为不同的命名空间。
    【解决方案3】:

    您发布的 XML 文档实际上格式不正确,因为分配给许多元素的 ns2 缩写与命名空间无关。已修复,可能如下所示:

    <ns1:E xmlns:ns1="schema" xmlns:ns2="my-namespace">
      <ns1:B>
        <ns2:S>
          <ns2:V>
            <ns2:Bl />
           </ns2:V>
        </ns2:S>
      </ns1:B>
    </ns1:E>
    

    上面的 XML 文档在语义上等价于这个:

    <s:E xmlns:s="schema">
      <s:B>
        <S xmlns="my-namespace">
          <m:V xmlns:m="my-namespace">
            <s:Bl xmlns:s="my-namespace"/>
          </m:V>
        </S>
      </s:B>
    </s:E>
    

    还有这个:

    <E xmlns="schema">
      <B xmlns="schema">
        <S xmlns="my-namespace">
          <V>
            <Bl/>
          </V>
        </S>
      </B>
    </E>
    

    在所有三种情况下,EB 元素都在 schema 命名空间中,而 SVBl 元素在 my-namespace 命名空间中。

    命名空间前缀很有帮助,但严格来说它们是不必要的。您可以创建 XML 文档,就像上一个示例一样,不使用前缀,并为每个元素显式声明命名空间。

    如果在处理 XML 时,您认为您关心给定元素使用的前缀,那您几乎肯定是错的。您唯一关心的是它属于哪个名称空间。例如,如果我将这三个文档中的 任何 加载到 XmlDocument 中,以下代码将写出 'Bl' 元素:

        XmlNamespaceManager ns = new XmlNamespaceManager(d.NameTable);
        ns.AddNamespace("a", "schema");
        ns.AddNamespace("b", "my-namespace");
        Console.Write(d.SelectSingleNode("/a:E/a:B/b:S/b:V/b:Bl", ns).OuterXml);
    

    当你说:

    我不希望输出具有架构引用,但我确实需要具有前缀。我想要达到的结果就是&lt;ns1:E&gt;

    你几乎肯定是错的。标签为ns1:E 的元素是没有意义的,除非ns1 前缀映射到命名空间,无论是在该元素中还是在其祖先之一中。 (此外,命名空间不是架构引用。)如果您使用

    CreateElement("ns1", "E", "schema");
    

    创建元素,然后将其附加到已将 ns1 声明为 schema 命名空间前缀的元素,然后 DOM 将附加没有命名空间声明的元素,因为在该上下文中它不需要。如果ns1 没有被声明(或者被声明为schema 以外的某个命名空间的缩写),那么 DOM 会在元素和前缀上粘贴命名空间声明。

    tl;dr:你关心的是命名空间,而不是命名空间前缀。

    【讨论】:

      【解决方案4】:

      (我知道这是一个老问题,但我正在做一些等效的事情,并想出了如何挥动死鸡使其工作。我正在记录它,以便以后找到它。)

      字符串 myName = "foo";
      
      字符串 ns_local = root.GetNamespaceOfPrefix("local");
      字符串 ns_x = root.GetNamespaceOfPrefix("x");
      
      System.Xml.XmlNode newNode = doc.CreateNode(System.Xml.XmlNodeType.Element, "local", "MyTag", ns_local);
      
      System.Xml.XmlNode attr = doc.CreateNode(System.Xml.XmlNodeType.Attribute, "Key", ns_x);
      attr.Value = 我的名字;
      newNode.Attributes.SetNamedItem(attr);
      
      attr = doc.CreateNode(System.Xml.XmlNodeType.Attribute, "MyAttr", "");
      attr.Value = 我的名字;
      newNode.Attributes.SetNamedItem(attr);
      
      nodeToAppendTo.AppendChild(newNode);
      

      这给了我一个看起来像

      的标签
      <local:MyTag x:Key="foo" MyAttr="foo" />
      

      【讨论】:

      • 迄今为止最好的实际例子。
      【解决方案5】:
      <ns1:E xmlns:ns1="schema">
          <ns1:B>
             <ns2:S>
               <ns2:V>
                 <ns2:Bl />
               </ns2:V>
             </ns2:S>
          </ns1:B>
      </ns1:E>
      

      所以要使用 Create XmlElement 获得上述输出,可以如下实现:

      CreateElement("ns1","E", "schema");
      CreateElement("ns1","B", "schema");
      CreateElement("ns2","S", "schema");
      CreateElement("ns2","V", "schema");
      CreateElement("ns2","B1", "schema");
      

      这里元素“E”是根元素,所以它的前缀是“ns1”以及架构。

      由于所有其他提到的元素,如“B”、“S”、“V”、“B1”,都是“E”的子元素,它以提到的前缀作为前缀,但不会再次显示子元素的架构。

      因此,您可以在根元素中获得所需的输出,并且只有子元素的前缀。

      【讨论】:

        【解决方案6】:

        冒号前的单词是命名空间。如果你想拥有一个元素“ns1:E”,你需要创建一个名为“E”的元素并将其命名空间设置为“ns1”。

        【讨论】:

        • 谢谢,有道理,但不知何故我还没有得到我想要的结果。不知道为什么。如果我指定 uri 或 ns 引用,则元素名称是正确的,但它会将引用添加到我不想要的输出。如果我不这样做,则不会添加前缀。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多