代码之家  ›  专栏  ›  技术社区  ›  bmargulies

javaxmldom:id属性有何特殊性?

  •  19
  • bmargulies  · 技术社区  · 14 年前

    用于 Document getElementById .

    因此,我将一个XHTML文档读入DOM(使用xerces2.9.1)。

    <p id='fribble'> 在里面。

    getElementById("fribble") ,并返回null。

    所以,问题是,是什么导致了 DocumentBuilder 将ID属性标记为“如此定义”

    5 回复  |  直到 14 年前
        1
  •  18
  •   Tom Tresansky    14 年前

    getElementById() 打电话上班 Document 必须知道其节点的类型,并且目标节点必须是XML ID类型,方法才能找到它。它通过一个相关的模式知道其元素的类型。如果未设置架构或未声明 id 属性的XML ID类型, getElementById()

    我猜你的文件不知道 p 元素的 身份证件 属性是XML ID类型(是吗?)。可以使用导航到DOM中的节点 getChildNodes() Attr.isId() 在id属性上确定。

    getElementById javadoc公司:

    DOM实现应该 使用属性Attr.isId 身份证件。

    “id”不属于id类型,除非是这样

    如果您使用的是 DocumentBuilder 要将XML解析为DOM,请务必调用 setSchema(schema) 在调用newDocumentBuilder()之前,在DocumentBuilderFactory上,确保从工厂获得的生成器知道元素类型。

        2
  •  51
  •   Dev-iL    6 年前

    类型 也不是因为他们 名称

    尽管属性很容易被认为是 name="value" 属性类型 与属性关联。

    当涉及到XML模式时,这很容易理解,因为XML模式支持XML元素和XML属性的数据类型。XML属性被定义为简单类型(例如xs:string、xs:integer、xs:dateTime、xs:anyURI)。这里讨论的属性是用 xs:ID section 3.3.8 of the XML Schema Part 2: Datatypes ).

    <xs:element name="foo">
      <xs:complexType>
       ...
       <xs:attribute name="bar" type="xs:ID"/>
       ...
      </xs:complexType>
    </xs:element>
    

    尽管DTD不支持XML模式中的丰富数据类型,但它确实支持有限的数据类型集 属性类型 (定义见 section 3.3.1 of XML 1.0 属性类型 ID .

    <!ATTLIST foo  bar ID #IMPLIED>
    

    <foo bar="xyz"/>
    

    如果不知道XML模式或DTD,就无法判断什么是ID,什么不是:

    • 属性类型
    • 名称不是“id”的属性可能具有 身份证号码!

    为了改善这种状况 xml:id 后来发明了(见 xml:id W3C Recommendation 但是,它是否存在将取决于所使用的解析器是否知道 xml:id 已定义,可能不受支持。

    Java中的IDs

    在爪哇, getElementById() 类型 ID,不适用于具有 “id”的名称。

    在上面的例子中, getElementById("xyz") foo bar 有一个 属性类型

    那么DOM怎么知道呢 属性类型 属性具有吗?有三种方法:

    1. 向解析器提供XML模式( example
    2. 向解析器提供DTD
    3. 显式地向DOM指示它被视为ID的属性类型。

    setIdAttribute() setIdAttributeNS() setIdAttributeNode() 上的方法 org.w3c.dom.Element class

    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”)的属性的所有出现都是 属性类型 身份证件。

    第三种方法仅在调用 getElementById() getElementById()

    另外,请注意,这些方法不在原始DOM规范中。这个 getElementById 于年引进 DOM level 2

    XPath中的ID

    原始问题中的XPath给出了一个结果,因为它只与属性匹配 .

    匹配 ID值,XPath id 函数需要使用(它是 Node Set Functions from XPath 1.0 ):

    id("xyz")
    

    如果使用了它,XPath将给出与之相同的结果 getElementById() (即未找到匹配项)。

    ID的两个重要特性应该被强调。

    首先,所有属性的值 ID必须是 . 在下面的示例中,如果 personId companyId 属性类型 公司ID 这很重要。

    <test1>
     <person personId="id24600">...</person>
     <person personId="id24601">...</person>
     <company companyId="id12345">...</company>
     <company companyId="id12346">...</company>
    </test1>
    

    第二,法律 而不是整个XML文档。因此,在不同元素上具有相同属性名称的属性可能具有不同的 属性类型 属性。在下面的示例XML文档中,如果 alpha/@bar 有一个 属性类型 将返回一个元素,但是 getElementById("abc") 不会(因为 beta/@bar 不属于 ID)。而且,这不是属性的错误 gamma/@bar 具有与…相同的价值 ,在XML文档中ID的唯一性中不考虑该值,因为它不是唯一的 属性类型

    <test2>
      <alpha bar="xyz"/>
      <beta bar="abc"/>
      <gamma bar="xyz"/>
    </test2>
    
        3
  •  4
  •   Sergii Pozharov    14 年前

    ID属性不是名为“ID”的属性,而是DTD或schema声明为ID属性的属性。例如,html 4 DTD描述了它:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    
        4
  •  3
  •   Jörn Horstmann    14 年前

    相应的xpath表达式实际上是 id('fribble') getElementById . 为此,与文档相关联的dtd或schema必须将属性声明为ID类型。

    xml:id 根据 http://www.w3.org/TR/xml-id/

        5
  •  1
  •   Brad Parks    11 年前

    以下内容将允许您按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;
        }
    }