How to Create Xmlelement Attributes with Prefix

How to create XmlElement attributes with prefix?

If you've already declared your namespace in the root node, you just need to change the SetAttribute call to use the unprefixed attribute name. So if your root node defines a namespace like this:

<People xmlns:s='http://niem.gov/niem/structures/2.0'>

You can do this and the attribute will pick up the prefix you've already established:

// no prefix on the first argument - it will be rendered as
// s:id='ID_Person_01'
TempElement.SetAttribute("id", "http://niem.gov/niem/structures/2.0", "ID_Person_01");

If you have not yet declared the namespace (and its prefix), the three-string XmlDocument.CreateAttribute overload will do it for you:

// Adds the declaration to your root node
var attribute = xmlDocToRef.CreateAttribute("s", "id", "http://niem.gov/niem/structures/2.0");
attribute.InnerText = "ID_Person_01"
TempElement.SetAttributeNode(attribute);

Adding a prefix to an xml node

If you are trying to add namespace to the elements after loading the xml document then it is not possible.

From MSDN:

You cannot add, modify, or delete an
XML namespace definition in an
instance of an XML document after the
document has been loaded into the XML
Document Object Model (XMLDOM) parser.
The XML nodes that are used to
represent data in the XML document are
created when the document is loaded
into the XMLDOM parser. These nodes
are permanently bound to their XML
namespace attributes when they are
created. Therefore, the empty XML
namespace declaration (xmlns = "") is
appended to the child nodes of these
nodes to preserve the default XML
namespace attribute of these nodes.

However you can load the input, read each element and write it to another document (or in-memory) which has the namespace set.
Below is the code that parses the string xml, creates a new xml element along with namespace prefix and namespace.

            String xmlWithoutNamespace =
@"<Folio><Node1>Value1</Node1><Node2>Value2</Node2><Node3>Value3</Node3></Folio>";
String prefix ="vs";
String testNamespace = "http://www.testnamespace/vs/";
XmlDocument xmlDocument = new XmlDocument();

XElement folio = XElement.Parse(xmlWithoutNamespace);
XmlElement folioNode = xmlDocument.CreateElement(prefix, folio.Name.LocalName, testNamespace);

var nodes = from node in folio.Elements()
select node;

foreach (XElement item in nodes)
{
var node = xmlDocument.CreateElement(prefix, item.Name.ToString(), testNamespace);
node.InnerText = item.Value;
folioNode.AppendChild(node);
}

xmlDocument.AppendChild(folioNode);

xmlDocument now contains the xml with each node prefixed with vs.

How to add multiple different prefixed attributes in XmlDocument

Got answer on my own.

var fourthAttribute = objXMLDocument.CreateAttribute("xsi",   "schemaLocation", "http://www.w3.org/2001/XMLSchema-instance"); 
fourthAttribute.InnerText = "xyz.....";
nodeDeclaration.Attributes.Append(objAttribute);

This is how it should be

Is it possible to create an XmlElement with two xml namespaces?

You can do this as follows:

var fooNs = "http://www.example.com/xmlns/foo-version1";
var defNs = "http://www.example.com/xmlns";

var doc = new XmlDocument();

// Create and add the root element
var root = doc.CreateElement("foo", "document", fooNs);
doc.AppendChild(root);

// Add the default namespace (do note the root element is not in this namespace)
var defAttr = doc.CreateAttribute("xmlns");
defAttr.Value = defNs;
root.Attributes.Append(defAttr);

// Create the <foo:bar> element
var bar = doc.CreateElement("foo", "bar", fooNs);
var bazAttr = doc.CreateAttribute("foo", "baz", fooNs);
bazAttr.Value = XmlConvert.ToString(true);
bar.Attributes.Append(bazAttr);

// Add it to the root
root.AppendChild(bar);

Notes:

  • When creating XmlElement and XmlAttribute nodes in a namespace, always prefer to use the Create() overloads that take a prefix, a localName and a namespaceURI:

    • XmlDocument.CreateElement(String, String, String)
    • XmlDocument.CreateAttribute(String, String, String)


    From a semantic point of view, what really matters is the node local name and namespace; the prefix is just a lookup to find a namespace declaration in scope.

  • Notice I didn't explicitly add the xmlns:foo="http://www.example.com/xmlns/foo-version1" attribute? It is unnecessary to do this since the root element was created using the required namespace and prefix via doc.CreateElement("foo", "document", fooNs). The framework (XmlWriter) will automatically emit the xmlns:foo attribute as it writes the XmlDocument to XML.

    If for some reason you need to explicitly create the namespace attribute, you can do it as follows:

    // The following is redundant as the framework (XmlWriter) will add the necessary
    // xmlns:foo attribute as the XmlDocument is being written. If you need to do it anway
    // (e.g. to control the order) you can do it as follows.
    // (But note that XML attributes are unordered according to the XML specification, for details
    // see https://stackoverflow.com/questions/33746224/in-xml-is-the-attribute-order-important)
    var xmlnsNs = "http://www.w3.org/2000/xmlns/";

    var fooAttr = doc.CreateAttribute("xmlns", "foo", xmlnsNs);
    fooAttr.Value = fooNs;
    root.Attributes.Append(fooAttr);

Demo fiddle #1 here.

Incidentally, as written in comments, it's much easier to do this with LINQ to XML:

XNamespace fooNs = "http://www.example.com/xmlns/foo-version1";
XNamespace defNs = "http://www.example.com/xmlns";

var root = new XElement(fooNs + "document"
// Add the namespace declarations with your desired prefixes. Be sure to pass them into the constructor.
, new XAttribute("xmlns", defNs.ToString())
, new XAttribute(XNamespace.Xmlns + "foo", fooNs.ToString())
// And add any required content. The content can be passed into the constructor, or added later.
, new XElement(fooNs + "bar", new XAttribute(fooNs + "baz", true)));

Notes:

  • With LINQ to XML you never need to worry about the namespace prefix of an XElement or XAttribute. Just create them with the correct namespace and local name as encapsulated by XName. The framework (XmlWriter) will automatically emit all necessary namespace attributes as it writes.

    But if you do need to configure namespaces for some reason you can construct appropriate XAttribute objects and then pass them into the XElement constructor.

  • For further reading see How to: Create a Document with Namespaces (C#) (LINQ to XML).

Demo fiddle #2 here.

Create XML element without namespace prefix inside element with namespace prefix

Changing your Root class like this should do it:

[XmlRoot(ElementName = "root", Namespace = "http://foo.bar")]
public class Root
{
// note empty namespace here
[XmlElement(ElementName = "child", Namespace = "")]
public Child Child { get; set; }
}


Related Topics



Leave a reply



Submit