faqts : Computers : Programming : Languages : JavaScript : XML

+ Search
Add Entry AlertManage Folder Edit Entry Add page to http://del.icio.us/
Did You Find This Entry Useful?

2 of 2 people (100%) answered Yes
Recently 2 of 2 people (100%) answered Yes

Entry

How can I create an attribute in a certain namespace with the DOM?
How can I create an xml:lang attribute with the DOM?

Mar 25th, 2005 05:25
Martin Honnen, http://www.w3.org/TR/DOM-Level-2-Core/core.html#i-Document http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-745549614 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk/html/xmmthcreateNode.asp


The W3C DOM Level 1 is not namespace aware but the W3C DOM Level 2 is.
If you want to attach an attribute in a certain namespace to an element
there are two ways in the DOM that you can do it, you can either use the
method setAttributeNS of the element itself to directly create the
attribute with a certain name and value and attach it to the element all
in one step, or you can use the method createAttributeNS of the XML
document to first create the attribute node in one step, give it a value
in a second step, and attach it to an element node calling the method
setAttributeNode of the element in a third step.

The method setAttributeNS of element nodes takes three arguments, the
first is a string with the namespace URI, the second the qualified name
of the attribute, and the third the string value of the attribute:

  element.setAttributeNS(
    'http://example.com/2005/03/ns1',
    'pf1:attribute-name',
    'Kibology for all'
  );

If element is originally an empty element e.g. <element-name /> then its
serialization after adding the attribute looks like

  <element-name 
    pf1:attribute-name="Kibology for all"     
    xmlns:pf1="http://example.com/2005/03/ns1"/>

thus as you can see the serialization automatically adds an xmlns:pf1
attribute to bind the prefix pf1 to the namespace URI used.

The method setAttributeNS of the W3C DOM Level 2 is currently
implemented by Mozilla and Mozilla based browsers (like Netscape 6/7).


The method createAttributeNS takes two arguments, the first is a string
with the namespace URI and the second the qualified attribute name:

  var attribute = xmlDocument.createAttributeNS(
    'http://example.com/2005/03/ns1',
    'pf1:attribute-name'
  );
  // set value
  attribute.nodeValue = 'Kibology for all';
  // attach to element
  element.setAttributeNode(attribute);

The method createAttributeNS of the W3C DOM Level 2 is currently
implemented by Mozilla and Mozilla based browsers (like Netscape 6/7)
but the preferred way is the method setAttributeNS.


IE/Win (5 and later) does not have its own XML DOM implementation but
instead makes use of MSXML which does not implement the W3C DOM Level 2
but is nevertheless namespace aware as it has a generic method
createNode of the XML document which takes three arguments, the first
being a number indicating the node type, the second being the node name,
and the third being a string with the namespace URI so to create an
attribute node with MSXML you need:

  var attribute = xmlDocument.createNode(
    2,
    'pf1:attribute-name',
    'http://example.com/2005/03/ns1'
  );
  // set value
  attribute.nodeValue = 'Kibology for all';
  // attach to element
  element.setAttributeNode(attribute);

Again if element is originally an empty element <example-element /> then
after adding the attribute its serialization looks alike 

  <example-element 
    xmlns:pf1="http://example.com/2005/03/ns1"
    pf1:attribute-name="Kibology for all"/>

thus the xmlns:pf1 attribute binding the prefix pf1 to the namespace URI
is automatically added during serialization.



Obviously if you want to write cross-browser code to create an attribute
in a namespace with the DOM then you need to check which method is
available, the following is an example that does that. It also shows how
to create special attributes like xml:lang or xmlns:prefix as for that
you need to use predefined namespace URIs:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
          "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Creating XML attributes in a namespace</title>
<script type="text/javascript">
function loadXMLFromString (markup) {
  var xmlDocument = null;
  if (typeof DOMParser != 'undefined') {
    xmlDocument = new DOMParser().parseFromString(markup,
'application/xml');
  }
  else if (typeof ActiveXObject != 'undefined') {
    /*@cc_on @*/
    /*@if (@_jscript_version >= 5)
    try {
      xmlDocument = new ActiveXObject('Microsoft.XMLDOM');
      xmlDocument.loadXML(markup);
    }
    catch (e) { }
    @end @*/  
  }
  return xmlDocument;
}

function setAttributeNodeNS (element, attributeName, attributeValue,
namespaceURI) {
  if (typeof element.setAttributeNS != 'undefined') {
    element.setAttributeNS(namespaceURI, attributeName, attributeValue);
  }
  else if (typeof element.ownerDocument != 'undefined' &&
           typeof element.ownerDocument.createNode != 'undefined') {
    var attribute = element.ownerDocument.createNode(
      2,
      attributeName,
      namespaceURI
    );
    attribute.nodeValue = attributeValue;
    element.setAttributeNode(attribute);
  }
}

function serializeNode (node) {
  if (typeof XMLSerializer != 'undefined') {
    return new XMLSerializer().serializeToString(node);
  }
  else if (typeof node.xml != 'undefined') {
    return node.xml;
  }
  else {
    return '';
  }
}
</script>
<script type="text/javascript">
function output (text) {
  var pre = document.createElement('pre');
  pre.appendChild(document.createTextNode(text));
  document.body.appendChild(pre);
}
</script>
</head>
<body>

<h1>Creating XML attributes in a namespace</h1>

<h2>Adding an attribute in an example namespace</h2>

<script type="text/javascript">
function example1 () {
  var exampleMarkup = '<example-element />';
  var xmlDocument = loadXMLFromString(exampleMarkup);
  setAttributeNodeNS(
    xmlDocument.documentElement, 
    'pf1:attribute-name',
    'Kibology for all',
    'http://example.com/2005/03/ns1'
  );
  output('Serialized XML:\r\n' + serializeNode(xmlDocument));
}

example1();
</script>

<h2>Adding an xml:lang attribute</h2>

<p>The prefix with name 'xml' is always bound to the namespace with the URI
http://www.w3.org/XML/1998/namespace.</p>

<script type="text/javascript">
function example2 () {
  var xmlNamespaceURI = 'http://www.w3.org/XML/1998/namespace';
  var exampleMarkup = '<text>Kibology for all.<\/text>';
  var xmlDocument = loadXMLFromString(exampleMarkup);
  setAttributeNodeNS(
    xmlDocument.documentElement, 
    'xml:lang',
    'en',
    xmlNamespaceURI
  );
  output('Serialized XML:\r\n' + serializeNode(xmlDocument));
}

example2();
</script>

<h2>Adding an xmlns:prefix attribute</h2>

<p>The prefix with name 'xmlns' is always bound to the namespace with
the URI
http://www.w3.org/2000/xmlns/. Note that with the DOM you usually do not
need
to add such an attribute with code, any XML serializer should automatically
create it when needed.</p>

<script type="text/javascript">
function example3 () {
  var xmlnsNamespaceURI = 'http://www.w3.org/2000/xmlns/';
  var exampleMarkup = '<element />';
  var xmlDocument = loadXMLFromString(exampleMarkup);
  setAttributeNodeNS(
    xmlDocument.documentElement, 
    'xmlns:prefix',
    'http://example.com/2005/03/ns2',
    xmlnsNamespaceURI
  );
  output('Serialized XML:\r\n' + serializeNode(xmlDocument));
}

example3();
</script>

</body>
</html>