如何使用Javascript查找带名称空间的HTML元素
How to use Javascript to find namespaced HTML elements
我正在写一些学术性的东西,其中我有按名称命名的HTML元素,如:
<ns:LinkList id="sitesuteis" cssClass="classone">
<ns:LinkItem id="LI1" href="http://www.ibt.pt/" target="_blank">IBT</ns:LinkItem>
<ns:LinkItem id="LI2" href="http://http://html5demos.com/t/" target="_blank">HTML5 Demos</ns:LinkItem>
<ns:LinkItem id="LI3" href="http://diveintohtml5.ep.io/" target="_blank">Dive into HTML5</ns:LinkItem>
<ns:LinkItem id="LI4" href="http://html5boilerplate.com/" target="_blank">HTML5 Boilerplate</ns:LinkItem>
</ns:LinkList>
现在,在JavaScript中,我正在尝试:
var elements = document.getElementsByTagName('ns:LinkItem');
element = elements[0];
console.log(element.getAttribute('id'));
//I get a correct value in all browsers
以获取我的elements[0]
中的所有子节点。它在所有浏览器中都能正常工作,除了-IELT9-
我试过了:
var children = element.getElementsByTagName('ns:LinkItem');
console.log(children.length);
和:
var children = Array();
for (i=0; i<element.childNodes.length; i++){
alert(element.childNodes[i].nodeName);
if (element.childNodes[i].nodeName=="NS:LINKITEM"){
children.push(element.childNodes[i]);
}
}
console.log(children.length);
在这两个console.log中,我在每个浏览器中都得到了正确的长度(4(,除了Internet Explorer 8或更低,我得到的是0。
根据@Shadow Wizard的说法,在Internet Explorer 8及以下版本中,元素的canHaveChildren
属性为false,这意味着死路一条,浏览器根本不支持该标记具有子节点,例如<br />
不能具有子节点。我试过了,这是真的。如果我尝试:
element.parentNode
在InternetExplorer8或更低版本中,我会得到包含我的标记的div
,而在其他浏览器中,我得到我的父<ns:LinkList>
。
我真的需要一个破解,但我似乎找不到。
在非Internet Explorer浏览器中,我建议getElementsByTagNameNS
获取特定命名空间中的元素。
在Internet Explorer中,您可以使用XPath。
jQuery还提供了一种使用名称空间的方法;它似乎在"使用名称空间进行jQueryXML解析"中有所介绍。
我相信下面的函数应该可以工作——我在以前的项目中使用过它,我相信它在InternetExplorer6、7和8中可以有效地工作。我没有一个在InternetExplorer9中测试的好方法,但我猜它应该能正常工作,因为InternetExplorer 9支持getElementsByTagNameNS
。它非常简单,并且依赖于核心浏览器方法。
/**
* Cross-browser implementation for namespaced tags
* @param {DOM Node} n Parent node
* @param {String} tag Tag name you're trying to retrieve
* @param {String} [ns] Namespace prefix
*/
getElementsByTagName = function(n, tag, ns) {
// map the namespace prefix to the full namespace URIs
var nsMap = {
'svg': 'http://www.w3.org/2000/svg'
// etc - whatever's relevant for your page
};
if (!ns) {
// no namespace - use the standard method
return n.getElementsByTagName(tag);
}
if (n.getElementsByTagNameNS && nsMap[ns]) {
// function and namespace both exist
return n.getElementsByTagNameNS(nsMap[ns], tag);
}
// no function, get with the colon tag name
return n.getElementsByTagName(ns + ':' + tag);
};
// get a list of svg:circle elements
getElementsByTagName(document, 'circle', 'svg');
这里唯一的痛点是需要定义从名称空间前缀到完整名称空间URI的映射。如果你想让它成为一个更可移植的函数,你可以把nsMap
作为一个函数参数,而不是在函数体中定义的东西;或者可以在全局上下文中引用名称空间映射对象。
这是一个完全模块化的版本,有一个稍微紧凑的getElementsByTagName
:版本
var namespaces = (function() {
var nsMap = {};
/**
* Add a new XML namespace with prefix
* @param {String} prefix Prefix for new namespace
* @param {String} uri Full URI of new namespace
*/
function addNamespace(prefix, uri) {
nsMap[prefix] = uri;
}
/**
* Cross-browser implementation for namespaced tags
* @param {DOM Node} [n] Parent node
* @param {String} tag Tag name you're trying to retrieve
* @param {String} [ns] Namespace prefix
*/
function getElementsByTagName(n, tag, ns) {
return !ns ?
n.getElementsByTagName(tag) :
(n.getElementsByTagNameNS && nsMap[ns]) ?
n.getElementsByTagNameNS(nsMap[ns], tag) :
n.getElementsByTagName(ns + ':' + tag);
}
return {
addNamespace: addNamespace,
getElementsByTagName: getElementsByTagName
};
}());
// set the svg namespace
namespaces.addNamespace('svg', 'http://www.w3.org/2000/svg');
// get a list of svg:circle elements
namespaces.getElementsByTagName(document, 'circle', 'svg');
在Internet Explorer 8及以下版本中,元素的canHaveChildren
属性是false
,这意味着死胡同,浏览器根本不支持此标记具有子节点,例如<br />
不能具有子节点。
不过,这在Internet Explorer 9中已经修复。
我从来没有遇到过这个问题,所以这只是一个建议或提示。
我为MSIE命名空间"restriction"找到了"getElementsByTagName(W3C DOM Core方法("。
我终于在"JavaScript中的XPath,第3部分"中找到了要点,它将确认XPath的使用将是要点:
默认情况下,Internet Explorer的XPath引擎不能与命名空间(与DOM Level 3 XPath实现相同(。命名空间信息必须提前指定为上的属性XML DOM文档对象本身。考虑以下XML代码:
<books xmlns:wrox="http://www.wrox.com/" xmlns="http://www.amazon.com/"> <wrox:book>Professional JavaScript</book> </books>
为了在此文档中使用XPath查询,您首先需要定义wrox和默认名称空间的名称空间信息。你可以通过setProperty((方法执行,传入"SelectionNamespaces"和以空格分隔的命名空间字符串声明。示例:
xmldoc.setProperty("SelectionNamespaces", "xmlns:wrox='http://www.wrox.com/' xmlns='http://www.amazon.com/'"); var book = xmldoc.documentElement.selectSingleNode("wrox:book");
请注意,命名空间声明的格式与它们相同出现在XML中。不幸的是,没有自动提取的方法文档中用于XPath的命名空间信息查询。结论
Internet Explorer确实支持XPath,但它有几个注意事项。首先,XPath查询只适用于XML文档,而不适用于在HTML文档上,因此无法在文档上使用以帮助查找元素。其次,XPath实现非常基础并且只允许基本的返回类型(节点和NodeSet对象(。还如果您处理的是XML数据,XPath仍然是一个快速方便的在不手动遍历DOM的情况下查找特定元素的方法。
这是一个破解,但它可能足够强大,可以满足您的需求:
function getElementsByTagName(parent, tagName)
{
if(typeof parent.canHaveChildren === 'undefined' || parent.canHaveChildren)
{
return parent.getElementsByTagName(tagName);
}
var elements = [];
var cursor = parent;
while(cursor.nextSibling && cursor.nextSibling.tagName !== ('/' + parent.tagName))
{
if(cursor.tagName === tagName.toUpperCase())
{
elements.push(cursor);
}
cursor = cursor.nextSibling;
}
return elements;
}
function getText(parent)
{
return parent.innerHTML || parent.nextSibling.data;
}
例如:
var element = document.getElementById('sitesuteis');
var children = getElementsByTagName(element, 'ns:LinkItem');
console.log(children.length);
for(var i = 0; i < children.length; i++)
{
console.log([getText(children[i]), children[i].getAttribute('href')]);
}
- html,js-如何限制元素"范围“-命名空间
- 静态html中图像之间的空间在javascript中消失
- 如何为HTML属性/选择器创建全局名称空间或变量
- 在html页面的属性周围添加了一个额外的空间
- 从html文件中的脚本标记调用非全局命名空间函数
- 影响JavaScript / CSS的HTML空间格式
- 使行占据 html 中的所有剩余空间
- 如何设置iframe以自动填充HTML中的空白正文空间
- 从 Javascript 字符串在 HTML 中呈现空间
- 如何修复 html 中的右列空间和底部容器空间
- JavaScript变量名称和HTML输入名称属性:名称空间冲突
- (jade)html标签;每个“;在i18next命名空间中
- HTML中的哪些空白空间被视为空白节点
- 用js隐藏HTML表行<tr>从而不占用空间
- CSS命名空间,HTML中的SVG:使用CSS突出显示SVG文件中的状态
- Html和CSS,给了我更大的工作空间,同时限制了文本的位置
- 使用html和js的移动应用程序的存储空间
- 如何调整HTML元素的高度以覆盖其所有可用空间'的父级
- 在html中占用一些额外空间的标签
- 绘制“负空间”;HTML