javaxmldom:id属性有什么特殊性?
javaxmldom:id属性有什么特殊性?,java,dom,Java,Dom,Document类的javadoc在getElementById下有以下注释 注意:名为“ID”或“ID”的属性不属于ID类型,除非这样定义 因此,我将一个XHTML文档读入DOM(使用Xerces 2.9.1) 文档中有一个普通的旧 我调用getElementById(“fribble”),它返回null 我使用XPath获取“/*[id='fribble']”,一切正常 因此,问题是,是什么导致DocumentBuilder实际将ID属性标记为“如此定义?”对于getElementById(
Document
类的javadoc在getElementById
下有以下注释
注意:名为“ID”或“ID”的属性不属于ID类型,除非这样定义
因此,我将一个XHTML文档读入DOM(使用Xerces 2.9.1)
文档中有一个普通的旧
我调用getElementById(“fribble”)
,它返回null
我使用XPath获取“/*[id='fribble']”,一切正常
因此,问题是,是什么导致
DocumentBuilder
实际将ID属性标记为“如此定义?”对于getElementById()
调用,文档必须知道其节点的类型,并且目标节点必须是XML ID类型,方法才能找到它。它通过关联的模式知道其元素的类型。如果未设置架构,或者未将id
属性声明为XML id类型,getElementById()
将永远找不到它
我猜您的文档不知道p
元素的id
属性是XML id类型(是吗?)。您可以使用getChildNodes()
和其他DOM遍历函数导航到DOM中的节点,并尝试在id属性上调用Attr.isId()
,以确定是否正确
从javadoc:
DOM实现预计将
使用属性Attr.isId可以
确定属性是否为类型
身份证
注意:名称为“ID”或
“id”不是id类型,除非如此
已定义。
如果使用DocumentBuilder
将XML解析为DOM,请确保在调用newDocumentBuilder()之前调用DocumentBuilderFactory,以确保从工厂获得的生成器知道元素类型。ID属性不是名为“ID”的属性,它是由DTD或模式声明为ID属性的属性。例如,html 4 DTD对其进行了描述:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
对应的xpath表达式实际上是id('fribble')
,它应该返回与getElementById
相同的结果。为此,与文档关联的dtd或模式必须将属性声明为ID类型
如果您控制查询的xml,您还可以尝试根据将属性重命名为xml:id
。这些属性之所以特殊,是因为它们的类型,而不是因为它们的名称
XML格式的ID
虽然很容易将属性视为name=“value”
,因为值是一个简单的字符串,但这并不是全部内容——还有一个属性类型与属性关联
当涉及XML模式时,这很容易理解,因为XML模式支持XML元素和XML属性的数据类型。XML属性被定义为简单类型(例如xs:string、xs:integer、xs:dateTime、xs:anyURI)。这里讨论的属性是用xs:ID
内置数据类型定义的(请参阅)
使用上述XML模式或DTD,以下元素将由ID值“xyz”标识
必须对每个元素节点执行此操作,这些节点上有一个此类属性。没有简单的内置方法可以使具有给定名称(例如“id”)的属性的所有引用都是属性类型id
第三种方法仅在调用getElementById()
的代码与创建DOM的代码分离的情况下有用。如果是相同的代码,它已经找到了设置ID属性的元素,因此不太可能需要调用getElementById()
另外,请注意,这些方法不在原始DOM规范中。中引入了getElementById
XPath中的ID
原始问题中的XPath给出了一个结果,因为它只匹配属性名
要匹配属性类型ID值,需要使用XPathID
函数(它是以下函数之一):
如果使用了它,XPath将给出与getElementById()
相同的结果(即未找到匹配项)
XML中的ID续
应该突出显示ID的两个重要特性
首先,属性类型ID的所有属性的值必须是整个XML文档唯一的。在下面的示例中,如果personId
和companyId
都具有ID属性类型,则添加另一个ID为companyId
的公司将是错误的,因为它将是现有ID值的副本。尽管属性名称不同,但重要的是属性类型
<test1>
<person personId="id24600">...</person>
<person personId="id24601">...</person>
<company companyId="id12345">...</company>
<company companyId="id12346">...</company>
</test1>
以下内容将允许您按id获取元素:
public static Element getElementById(Element rootElement, String id)
{
try
{
String path = String.format("//*[@id = '%1$s' or @Id = '%1$s' or @ID = '%1$s' or @iD = '%1$s' ]", id);
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList)xPath.evaluate(path, rootElement, XPathConstants.NODESET);
return (Element) nodes.item(0);
}
catch (Exception e)
{
return null;
}
}
不幸的是,到目前为止,指向模式示例的链接已经失效。
<foo bar="xyz"/>
Document doc;
Element fooElem;
doc = ...; // load XML document instance
fooElem = ...; // locate the element node "foo" in doc
fooElem.setIdAttribute("bar", true); // without this, 'found' would be null
Element found = doc.getElementById("xyz");
id("xyz")
<test1>
<person personId="id24600">...</person>
<person personId="id24601">...</person>
<company companyId="id12345">...</company>
<company companyId="id12346">...</company>
</test1>
<test2>
<alpha bar="xyz"/>
<beta bar="abc"/>
<gamma bar="xyz"/>
</test2>
public static Element getElementById(Element rootElement, String id)
{
try
{
String path = String.format("//*[@id = '%1$s' or @Id = '%1$s' or @ID = '%1$s' or @iD = '%1$s' ]", id);
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList)xPath.evaluate(path, rootElement, XPathConstants.NODESET);
return (Element) nodes.item(0);
}
catch (Exception e)
{
return null;
}
}