The Document Object Model (DOM) is one of the most common tools used to manipulate xml and HTML data. However, its potential is rarely fully explored. Document Object Model (DOM) is one of the most common tools used to manipulate xml and HTML data. However, its potential is rarely fully explored. By taking advantage of DOM and making it easier to use, you will get a powerful tool for XML applications, including dynamic Web applications.
This article introduces a guest columnist who is also my friend and colleague Dethe Elza. Dethe has rich experience in developing Web applications using XML. here, I would like to thank him for his help in introducing XML programming using DOM and ECMAScript. Please pay close attention to this column to learn more about Dethe columns.
-- David Mertz
DOM is one of the standard APIs for processing XML and HTML. It is often criticized for its high memory usage, slow speed, and lengthy usage. Even so, it is still the best choice for many applications, and it is much simpler than the second major API of XML-SAX. DOM is gradually appearing in some tools, such as Web browsers, SVG browsers, and OpenOffice.
DOM is good because it is a standard that is widely implemented and also built into other standards. As a standard, data processing is not related to programming languages (this may be an advantage or a disadvantage, but at least makes the way we process data consistent ). DOM is now not only built into Web browsers, but also part of many XML-based specifications. Since it has become part of your tool and you may occasionally use it, I think we should make full use of the features it brings to us now.
After using DOM for a while, you will see some patterns-what you want to do repeatedly. Shortcuts help you deal with lengthy DOM and create self-explanatory and elegant code. I have collected some tips and tricks I often use and some javaScript examples.
InsertAfter and PRependChild
The first trick is "no tricks ". DOM can be used to add a child node to a container node (usually an Element, or a Document or Document Fragment): appendChild (node) and insertBefore (node, referenceNode ). It seems that something is missing. What should I do if I want to insert a subnode after a reference node or add a subnode (so that the new node is first in the list? For many years, my solution has been to write the following functions:
Listing 1. Insert and add error methods before
function insertAfter(parent, node, referenceNode) { if(referenceNode.nextSibling) { parent.insertBefore(node, referenceNode.nextSibling); } else { parent.appendChild(node); }}function prependChild(parent, node) { if (parent.firstChild) { parent.insertBefore(node, parent.firstChild); } else { parent.appendChild(node); }}
In fact, like listing 1, the insertBefore () function has been defined and is returned to appendChild () when the reference node is empty (). Therefore, you can use the methods in listing 2 instead of the above method, or skip them and use only the built-in functions:
Listing 2. Insert and add the correct method before
function insertAfter(parent, node, referenceNode) { parent.insertBefore(node, referenceNode.nextSibling);}function prependChild(parent, node) { parent.insertBefore(node, parent.firstChild);}
If you are new to DOM programming, it is worth noting that although you can point multiple pointers to one node, the node can only exist in one position in the DOM tree. Therefore, if you want to insert it into the tree, you do not need to remove it from the tree because it will be automatically removed. This mechanism is convenient when you sort nodes again. you only need to insert the nodes to a new location.
Based on this mechanism, if you want to switch the locations of two adjacent nodes (node1 and node2), you can use one of the following solutions:
Node1.parentNode. insertBefore (node2, node1 );
Or
Node1.parentNode. insertBefore (node1.nextSibling, node1 );
What can I do with DOM?
DOM is widely used in Web pages. If you visit the bookmarklets Site (see references), you will find many creative short scripts that can re-orchestrate pages, extract links, hide images or Flash ads, and so on.
However, because Internet Explorer does not define a Node interface constant (which can be used to identify Node types), you must first define an interface constant for the Web in the DOM script when an interface constant is missing.
Listing 3. make sure the node is defined
if (!window['Node']) { window.Node = new Object(); Node.ELEMENT_NODE = 1; Node.ATTRIBUTE_NODE = 2; Node.TEXT_NODE = 3; Node.CDATA_SECTION_NODE = 4; Node.ENTITY_REFERENCE_NODE = 5; Node.ENTITY_NODE = 6; Node.PROCESSING_INSTRUCTION_NODE = 7; Node.COMMENT_NODE = 8; Node.DOCUMENT_NODE = 9; Node.DOCUMENT_TYPE_NODE = 10; Node.DOCUMENT_FRAGMENT_NODE = 11; Node.NOTATION_NODE = 12;}
Listing 4 shows how to extract all text nodes contained in a node:
Listing 4. internal text
function innerText(node) { // is this a text or CDATA node? if (node.nodeType == 3 || node.nodeType == 4) { return node.data; } var i; var returnValue = []; for (i = 0; i < node.childNodes.length; i++) { returnValue.push(innerText(node.childNodes[i])); } return returnValue.join('');}
Shortcut
People often complain that DOM is too lengthy and that a large amount of code is required for simple functions. For example, if you want to create
The code may be similar:
Listing 5. Create
"A Long Journey"
function handle_button() { var parent = document.getElementById('myContainer'); var p = document.createElement('p'); p.className = 'myDivCSSClass'; p.id = 'myDivId'; p.style.position = 'absolute'; p.style.left = '300px'; p.style.top = '200px'; var text = "This is the first text of the rest of this code"; var textNode = document.createTextNode(text); p.appendChild(textNode); parent.appendChild(p);}
If you frequently create nodes in this way, typing all the code will soon exhaust you. There must be a better solution-such a solution indeed! The following Utility helps you create elements, set element attributes and styles, and add text subnodes. Other parameters except the name parameter are optional.
Listing 6. function elem () shortcut
function elem(name, attrs, style, text) { var e = document.createElement(name); if (attrs) { for (key in attrs) { if (key == 'class') { e.className = attrs[key]; } else if (key == 'id') { e.id = attrs[key]; } else { e.setAttribute(key, attrs[key]); } } } if (style) { for (key in style) { e.style[key] = style[key]; } } if (text) { e.appendChild(document.createTextNode(text)); } return e;}
With this shortcut, you can create
Element. Note that the attrs and style parameters are provided using Javascript text objects.
Listing 7. Create
Easy way
function handle_button() { var parent = document.getElementById('myContainer'); parent.appendChild(elem('p', {class: 'myDivCSSClass', id: 'myDivId'} {position: 'absolute', left: '300px', top: '200px'}, 'This is the first text of the rest of this code'));}
This utility saves you a lot of time when you want to quickly create a large number of complex DHTML objects. The mode here means that if you have a specific DOM structure that needs to be frequently created, you can use a utility to create them. This not only reduces the amount of code you write, but also reduces repeated code cutting and pasting (the culprit of the error), and provides a clearer idea when reading the code.
What is next?
DOM is usually hard to tell you what the next node is in the order of documents. There are some practical tools to help you move between nodes:
Listing 8. nextNode and prevNode
// return next node in document orderfunction nextNode(node) { if (!node) return null; if (node.firstChild){ return node.firstChild; } else { return nextWide(node); }}// helper function for nextNode()function nextWide(node) { if (!node) return null; if (node.nextSibling) { return node.nextSibling; } else { return nextWide(node.parentNode); }}// return previous node in document orderfunction prevNode(node) { if (!node) return null; if (node.previousSibling) { return previousDeep(node.previousSibling); } return node.parentNode;}// helper function for prevNode()function previousDeep(node) { if (!node) return null; while (node.childNodes.length) { node = node.lastChild; } return node;}
Easy to use DOM
Sometimes you may want to traverse the DOM and call a function on each node or return a value from each node. In fact, because these ideas are very universal, DOM Level 2 already contains an extension called DOM Traversal and Range (defining objects and APIs for all nodes in the iterative DOM ), it is used to apply functions to all nodes in the DOM and select a range in the DOM. Because these functions are not defined in Internet Explorer (at least currently), you can use nextNode () to do some
Something similar.
Here, our idea is to create some simple and common tools and then assemble them in different ways to achieve the expected results. It looks friendly if you are familiar with functional programming. The Beyond JS library (see references) carries forward this concept.
Listing 9. functional DOM utility
// return an Array of all nodes, starting at startNode and// continuing through the rest of the DOM treefunction listNodes(startNode) { var list = new Array(); var node = startNode; while(node) { list.push(node); node = nextNode(node); } return list;}// The same as listNodes(), but works backwards from startNode.// Note that this is not the same as running listNodes() and// reversing the list.function listNodesReversed(startNode) { var list = new Array(); var node = startNode; while(node) { list.push(node); node = prevNode(node); } return list;}// apply func to each node in nodeList, return new list of resultsfunction map(list, func) { var result_list = new Array(); for (var i = 0; i < list.length; i++) { result_list.push(func(list[i])); } return result_list;}// apply test to each node, return a new list of nodes for which// test(node) returns truefunction filter(list, test) { var result_list = new Array(); for (var i = 0; i < list.length; i++) { if (test(list[i])) result_list.push(list[i]); } return result_list;}
Listing 9 contains four basic tools. The listNodes () and listNodesReversed () functions can be extended to an optional length, which is similar to the effect of the Array slice () method. I will leave this for your exercise. Another thing to note is that map () and filter () functions are completely common and used to process any list (not just the node list ). Now, I will show you several combinations of them.
Listing 10. Using a functional utility
// A list of all the element names in document orderfunction isElement(node) { return node.nodeType == Node.ELEMENT_NODE;}function nodeName(node) { return node.nodeName;}var elementNames = map(filter(listNodes(document),isElement), nodeName);// All the text from the document (ignores CDATA)function isText(node) { return node.nodeType == Node.TEXT_NODE;}function nodeValue(node) { return node.nodeValue;}var allText = map(filter(listNodes(document), isText), nodeValue);
You can use these utilities to extract the ID, modify the style, find a node, and remove it. Once DOM Traversal and Range APIs are widely implemented, you can use them to modify the DOM tree without building the list first. They are not only powerful, but also work in a similar way as I mentioned above.
Dangerous zone of DOM
Note that the core dom api does not allow you to parse XML data to the DOM or serialize the DOM into XML. These functions are defined in the extension section "Load and Save" of DOM Level 3, but they are not fully implemented yet, so do not consider these. Each platform (a browser or other professional DOM application) has its own conversion method between DOM and XML, but cross-platform conversion is not covered in this article.
DOM is not a safe tool-especially when DOM APIs are used to create trees that cannot be serialized as XML. Do not mix the DOM1 non-namespace API and DOM2 namespace-aware API (for example, createElement and createElementNS) in the same program ). If you use a namespace, try to declare all namespaces at the root element location and do not overwrite the namespace prefix. Otherwise, the situation will be messy. In general, as long as you follow the convention, it will not trigger the critical situation that puts you in trouble.
If you have been using the innerText and innerHTML of Internet Explorer for parsing, you can try using the elem () function. By building similar utility tools, you will get more convenience and inherit the superiority of cross-platform code. Mixing these two methods is very bad.
Some Unicode characters are not included in XML. DOM implementation allows you to add them, but the consequence is that they cannot be serialized. These characters include most of the control characters and a single character in the Unicode proxy pair (surrogate pair. This happens only when you try to include binary data in the document, but this is another kind of turning situation (gotcha.
Conclusion
I have already introduced many things that DOM can do, but DOM (and JavaScript) can do more than that. Take a closer look at these examples to see how they are used to solve problems that may require client scripts, templates, or specialized APIs.
DOM has its own limitations and disadvantages, but it also has many advantages: it is built into many applications; whether using Java technology, Python or JavaScript, it works in the same way; it is very easy to use. with the above template, it is simple and powerful. More and more applications are beginning to support DOM, including Mozilla-based applications, OpenOffice, and XMetaL for Blast Radius. More and more specifications require DOM and extend it (for example, SVG), so DOM is always around you. It is wise to use this widely deployed tool.
The above is the XML question: Beyond the DOM (easy to use DOM skills and tips) content, for more information, please follow the PHP Chinese network (www.php1.cn )!