The prefix " cannot be redefined from " to <url> within the same start element tag
Asked Answered
B

3

41

I'm trying to generate the following xml element using C#.

<Foo xmlns="http://schemas.foo.com" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://schemas.foo.com
 http://schemas.foo.com/Current/xsd/Foo.xsd">

The problem that I'm having is that I get the exception:

The prefix " cannot be redefined from " to within the same start element tag.

This is my c# code:

XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
XElement foo = new XElement("Foo", new XAttribute("xmlns", "http://schemas.foo.com"),
                                   new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance"),
                                   new XAttribute(xsi + "schemaLocation", "http://schemas.foo.com http://schemas.foo.com/Current/xsd/Foo.xsd"));

How can I fix this? I'm trying to send the generated xml as the body of a SOAP message and I need it to be in this format for the receiver.

EDIT: I found my answer on another question. Controlling the order of XML namepaces

Bedad answered 16/5, 2014 at 15:11 Comment(2)
Prompted by the fact that there is a new answer to this question if you found the answer you should answer this question with the fix that worked for you rather than just editing the question to say you have an answer. Unless this question is actually a duplicate of the other in which case it should be marked as such but it doesn't seem to be an exact duplicate.Whittier
I found a solution to this problem here... [guyellisrocks.com/2009/03/…. It seemed like I needed to define the default namespace when the XDoc was defined. HTH.Coercion
S
38

You need to indicate that the element Foo is part of the namespace http://schemas.foo.com. Try this:

XNamespace xNamespace = "http://schemas.foo.com";    
XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
XElement foo = new XElement(
    xNamespace + "Foo", 
    new XAttribute("xmlns", "http://schemas.foo.com"),
    new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance"),
    new XAttribute(xsi + "schemaLocation", "http://schemas.foo.com http://schemas.foo.com/Current/xsd/Foo.xsd")
    );
Sacker answered 3/11, 2014 at 12:19 Comment(0)
C
11

I was getting this error when creating an XDocument. After a lot of googling I found this article:

http://www.mikesdotnetting.com/Article/111/RSS-Feeds-and-Google-Sitemaps-for-ASP.NET-MVC-with-LINQ-To-XML

There just happens to be an explanation part way through the doc, that I was lucky enough to spot.

The key point is that your code should let the XDocument handle the xmlns attribute. When creating an XElement, your first instinct would be to set the namespace attribute like all the rest, by adding an attribute "xmlns" and setting it to a value.

Instead, you should create an XNamespace variable, and use that XNamespace variable when defining the XElement. This will effectively add an XAttribute to your element for you.

When you add an xmlns attribute yourself, you are telling the XElement creation routine to create an XElement in no namespace, and then to change the namespace using the reserved xmlns attribute. You are contradicting yourself. The error says "You cannot set the namespace to empty, and then set the namespace again to something else in the same tag, you numpty."

The function below illustrates this...

    private static void Test_Namespace_Error(bool doAnError)
    {
        XDocument xDoc = new XDocument();
        string ns = "http://mynamespace.com";
        XElement xEl = null;
        if (doAnError)
        {
            // WRONG: This creates an element with no namespace and then changes the namespace
            xEl = new XElement("tagName", new XAttribute("xmlns", ns));
        }
        else
        {
            // RIGHT: This creates an element in a namespace, and implicitly adds an xmlns tag
            XNamespace xNs = ns;
            xEl = new XElement(xNs + "tagName");
        }

        xDoc.Add(xEl);
        Console.WriteLine(xDoc.ToString());
    }
Coercion answered 24/7, 2019 at 9:46 Comment(4)
This is great! Apparently it has one huge drawback though: Doing this on the root only anyway force-adds xmlns="" to all other sub XElements as well .. so we will have to either pass in this namespace to ... everything - or find a way to skip this force added empty namespace everywhereLyse
I thought the root having the namespace, and all sub elements have no namespace, would make all the sub elements inherit the root's namespace?Coercion
exatcly this would happen ... however XDocument (at least for) automatically added xmlns="" to all childs of the root as soon as I added the samespace to the root using your method ... for now I solved it by simply passing on the namespace into each and every XElement which results in the file as you describe it: xmlns added only to the root, all others do not have the attribute ... would be nice though if there was an option to make it behave different in the first placeLyse
Yes, I would maybe set a class or global variable (sacrilege!) to hold the preferred namespace, to avoid having to pass it around, but whatever works for you is good. Hopefully this helps others work around this annoying issue, thanks.Coercion
T
0

Others explain why this is happening but it still took me a while to work out how to fix it for me. I was trying to add some external XML to an XML document.

What finally worked for me was:

    ElementTree.register_namespace("mstts", "https://www.w3.org/2001/mstts")
    ElementTree.register_namespace("", "http://www.w3.org/2001/10/synthesis")
    xml_body = ElementTree.fromstring(
        '<speak version="1.0"'
        '  xmlns:mstts="https://www.w3.org/2001/mstts"'
        '  xmlns="http://www.w3.org/2001/10/synthesis"'
        f' xml:lang="{locale}">'
        f'  <voice name="{azure_voice}">'
        '       <mstts:silence type="Leading" value="0" />'
        '           <prosody rate="-10.00%">'
        f'              {utterance}'
        '           </prosody>'
        '       <mstts:silence type="Tailing" value="0" />'
        '   </voice>'
        '</speak>'
Tana answered 26/1, 2023 at 17:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.