带冒号的xml元素名称

时间:2009-11-24 19:12:22

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

我正在攻击第三方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

只要从元素名称中删除冒号,这就可以正常工作。使用冒号,只有冒号的右侧是元素名称。我知道冒号是禁止的,但我无法控制第三方api的命令。

有什么方法可以解决这个问题?是否有任何有用的方法可以强制冒号进入元素名称?我不必使用XMLDocument但不确定其他方法会让我在那里。

更新:我意识到<ns1:指的是命名空间。是的,有2.当写出XML时,如果我说 -

,我可以使它工作
 XmlDocument.CreateElement(ns1:E", "http://schema);

但是,这个的XML输出是

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

如果我只说XmlDocument.CreateElement("ns1:E");没有uri,那么输出只是<E>。我不希望输出具有架构引用,但我需要有前缀。我想要实现的结果只是<ns1:E>。两个namspace都在顶部声明,我认为这意味着我必须在每个节点声明它们。

6 个答案:

答案 0 :(得分:12)

好的,就是这样。

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

如果它可以帮助其他人,请参考此处:http://msdn.microsoft.com/en-us/library/c22k3d47.aspx 1

答案 1 :(得分:5)

冒号表示这些元素位于ns1 namespace中。使用多个模式时需要这样做。假设文档仅使用ns1,它基本上等同于那些标签中没有任何“ns1:”。有关详细信息,请参阅this guide

答案 2 :(得分:5)

您发布的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命名空间中,而SV和{{1} }元素位于Bl命名空间中。

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

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

XmlDocument

当你说:

  

我不希望输出具有架构引用,但我需要有前缀。我想要实现的结果只是 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);

你几乎肯定是错误的。标记为<ns1:E>的元素没有意义,除非ns1:E前缀映射到该元素或其祖先之一的命名空间。 (另外,命名空间不是架构引用。)如果使用

ns1

创建元素,然后将它附加到已经声明CreateElement("ns1", "E", "schema"); 作为ns1命名空间的前缀的元素,然后DOM将附加没有命名空间声明的元素,因为在这种情况下,它是不需要的。如果未声明schema(或声明为缩写ns1以外的某些命名空间),则DOM将在元素和前缀上添加名称空间声明。

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

答案 3 :(得分:3)

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

string myName = "foo";

string ns_local = root.GetNamespaceOfPrefix("local");
string 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 = myName;
newNode.Attributes.SetNamedItem(attr);

attr = doc.CreateNode(System.Xml.XmlNodeType.Attribute, "MyAttr", "");
attr.Value = myName;
newNode.Attributes.SetNamedItem(attr);

nodeToAppendTo.AppendChild(newNode);

这给了我一个看起来像

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

答案 4 :(得分:2)

<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");

这里元素&#34; E&#34;是根元素,所以它前缀为&#34; ns1&#34;以及架构。

由于所有其他提及的元素如&#34; B&#34;,&#34; S&#34;,&#34; V&#34;,&#34; B1&#34;是孩子的元素&#34; E&#34;它带有前面提到的前缀,但再次显示子元素的架构。

因此,您可以使用根元素中的模式获得上述所需的输出,并且只获得子元素的前缀。

答案 5 :(得分:0)

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