0

I have a XML file like this:

<?xml version="1.0" encoding="utf-8"?>
<ApplicationConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ua="http://opcfoundation.org/UA/2008/02/Types.xsd" xmlns="http://opcfoundation.org/UA/SDK/Configuration.xsd">
  <ServerConfiguration>
    <SecurityPolicies>
      <ServerSecurityPolicy>
        <SecurityMode>None_1</SecurityMode>
      </ServerSecurityPolicy>
    </SecurityPolicies>
  </ServerConfiguration>
</ApplicationConfiguration>

What I want is to add more node named ServerSecurityPolicy by code. Then I use this code:

            string docaddress = "D:\\abc.xml";
            XDocument doc = XDocument.Load(docaddress);
            var root = doc.Root;
            var these = root.Descendants().Where(p => p.Name.LocalName == "SecurityPolicies");
            XElement addelement = new XElement("ServerSecurityPolicy");
            addelement.Add(new XElement("SecurityMode", "None_1"));           
            foreach (var elem in these)
            {
                elem.Add(addelement);
            }
            doc.Save(docaddress);

It actually works, but the newly added node is something like this:

      <ServerSecurityPolicy xmlns="">
        <SecurityMode>None_1</SecurityMode>
      </ServerSecurityPolicy>

I don't want the attribute "xmlns", then I try to delete it by something like this:

            var these2 = root.Descendants().Where(p => p.Name.LocalName == "ServerSecurityPolicy");
            foreach (var elem in these2)
            {
                    label2.Text += elem.Attribute("xmlns").Name.LocalName;
                    elem.Attribute("xmlns").Remove();
            }

The label2.Text shows "xmlnsxmlnsxmlsn..." so that I think the elem.Attribute("xmlns") has pointed to the attributes I want to delete, but the Remove() not work. Can you suggest me some ways to delete the attribute or add node without attribute?
Thank you

5
  • 2
    Welcome to Stack Overflow. Your sample code doesn't compile, and having changed it to elem.Add(addelement); so that it will compile, the new node does not have xmlns="" in - using the XML file you've shown us. I suspect that's because you've only shown us part of the document, and the part you've omitted has set a root namespace. If you can provide a minimal reproducible example, it will be a lot easier to help you. Commented Aug 4, 2020 at 18:53
  • Hi Jon Skeet, thank you for replying. Firstly, you're right, I named the XElement "ro", but when post thread here, I think I should use something easier to observe, but I forget to change that last line. Secondly, because the xml file is quite long, so I just focus on some nodes to shorten and simplize the question, but from your answer, the error seems to be somewhere else. Can you help me to check the full xml file? Commented Aug 4, 2020 at 19:17
  • drive.google.com/file/d/1uO9nXAEBMOwCivV9VM9Nf1rQSl2Pn9fk/… Here's the xml file. Commented Aug 4, 2020 at 19:18
  • 1
    No, please don't just put it on Drive - please provide a minimal reproducible example in the question. (The purpose of Stack Overflow is to create a repository of high quality questions and answers. Someone else looking at your question in the future should be able to understand whether your question relates to theirs.) We don't need the actual full document - but we do need a full document that demonstrates the problem, along with code to reproduce the problem. Please edit the question to fix both the code (ideally turning it into a genuine complete console app ready to copy/paste) and the doc. Commented Aug 4, 2020 at 19:54
  • Hi Jon Skeet, thank you for specifing me how to work with Stack Overflow. I'm not sure about the console app, but I have edited my question as what I understand (and checked the code). Can you help me to re-check my problem? A few more detail, as you said before, I have check the root, and I think those attributes of it (<ApplicationConfiguration>) create the xmlns attribute of my new nodes. Commented Aug 4, 2020 at 20:42

2 Answers 2

1

The reason you're getting an empty attribute - which xmlns="" refers to - is because your document's root node belongs to the namespace xsi. When you're adding a node without a namespace - as you're doing in your example - you're not actually binding it to the xsi namespace.

To make your node part of the root namespace, replace

new XElement("ServerSecurityPolicy")

with

new XElement("ServerSecurityPolicy",
              new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance"))
Sign up to request clarification or add additional context in comments.

3 Comments

Hi @silkfire, I'm not sure about the namespace, but I think my root node share 2 namespaces (xsi and ua), right? So I try to add another XAttribute for the ua namespace. The problem is, the newly created nodes now have 3 different attributes, the xsi and ua are same as root node, and the xmlns="" (empty attribute). Have I done anything wrong?
@halaMurak: No, it's about the default namespace, which is http://opcfoundation.org/UA/SDK/Configuration.xsd
The document doesn't belong to the namespace with the alias xsi. It belongs to the http://opcfoundation.org/UA/SDK/Configuration.xsd namespace. The OP should create a new element in that namespace - there's no need to manually create an xmlns attribute as part of it. (See my answer, basically.)
0

The problem is that the element you want to create is actually in the http://opcfoundation.org/UA/SDK/Configuration.xsd namespace, which is the default for the document because of this part of the root element:

xmlns="http://opcfoundation.org/UA/SDK/Configuration.xsd"

You can create an element in that namespace easily:

XNamespace configNs = "http://opcfoundation.org/UA/SDK/Configuration.xsd";
var these = root.Descendants(configNs + "ServerSecurityPolicy");

When you add that to your document, you'll find it won't add the xmlns="" part, which was present because you were adding an element without a namespace.

I'd also suggest using the namespace to find elements too:

XNamespace configNs = "http://opcfoundation.org/UA/SDK/Configuration.xsd";
var these = root.Descendants(configNs + "SecurityPolicies");

That's much cleaner than just using the local name, in my view.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.