开发者

xml element name with colon

I'm working against a 3rd party xml api. They have defined a required xml structure similar to the following.

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

There is a SQL table with the information that I need to put into this xml format. I have a LINQ to S开发者_StackOverflowQL adapter to get the data and I'm using a System.Xml to create an XML document.

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

This works fine as long as I remove the colons from the element names. With the colons, only the right hand side of the colon is in the element name. I know colons are a no-no but I don't have any control over what the 3rd party api is dictating.

What are my options for getting around this? Are there any useful ways of forcing the colons into the element names? I don't have to use XMLDocument but not sure what other method will get me there.

UPDATE: I realize that the <ns1: refers to a namespace. And yes, there are 2. When writing out the XML, I can make it work if I say -

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

However, the XML output of this is

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

If I just say XmlDocument.CreateElement("ns1:E"); with no uri, then the output is just <E>. I don't want the output to have the schema reference but I do need to have the prefix. The result I want to achieve is simply <ns1:E>. Both namspaces are declared at the top which I would think would mean I would have to declare them at every node.


Okay, here it is.

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

reference here if it helps someone else: http://msdn.microsoft.com/en-us/library/c22k3d47.aspx 1


The colons indicate that those elements are in the ns1 namespace. This is needed when you are using multiple schemas. Assuming the document only uses ns1, it is essentially equivalent to not having any "ns1:" in those tags. See this guide for more info.


The XML document you posted is not actually well-formed, because the ns2 abbreviation assigned to many of the elements is not associated with a namespace. Fixed, it might look like this:

<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>

The above XML document is semantically equivalent to this one:

<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>

And to this one:

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

In all three cases, the E and B elements are in the schema namespace, while the S, V, and Bl elements are in the my-namespace namespace.

Namespace prefixes are helpful, but strictly speaking they're unnecessary. You can create XML documents, like the last example, that use no prefixes, and that declare the namespace explicitly for every element.

If, in processing XML, you think you care what prefix a given element is using, you're almost certainly wrong. The only thing you care about is what namespace it belongs to. For instance, if I load any of those three documents into an XmlDocument, the following code will write out the 'Bl' element:

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

When you say:

I don't want the output to have the schema reference but I do need to have the prefix. The result I want to achieve is simply <ns1:E>.

you are almost certainly in error. An element whose tag is ns1:E is meaningless unless the ns1 prefix is mapped to a namespace, either in that element or in one of its ancestors. (Also, a namespace is not a schema reference.) If you use

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

to create the element, and then append it to an element that has already declared ns1 as being the prefix for the schema namespace, then the DOM will append the element without the namespace declaration, because in that context it isn't needed. If ns1 isn't declared (or is declared as abbreviating some namespace other than schema), then the DOM will stick a namespace declaration onto the element as well as the prefix.

tl;dr: You care about namespaces, not namespace prefixes.


(I know it's an old question, but I'm doing something equivalent and figured out how to wave the dead chicken to make it work. I'm documenting it so I can find it later.)

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

This gives me a tag that looks like

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


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

So to get the output as above using Create XmlElement it could be achieved as below :

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

Here Element "E" is the root element so it prefixes it with "ns1" along with the schema.

Since all the other mentioned Elements like "B","S","V","B1" are child Elements of "E" it prefixes with the mentioned prefix but do not again displays the schema for the child Elements.

And hence you get the desired output as above with schema in the root element and only prefix for child elements.


The word before the colon is the namespace. If you want to have an element "ns1:E", you needs to create an element named "E" and set its namespace to "ns1".

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜