引用XML中的另一个元素

时间:2009-01-21 11:10:10

标签: xml xslt xpath

我正在尝试为我的应用程序设计XML文档结构。

我想存储一个像下面这样的漏洞列表

<Holes>
 <Hole id='1' dia='0.1' depth='2'/>
 <Hole id='2' dia='0.2' depth='1.67'/>
 <Hole id='3' dia='0.3' depth='0.44'/>
</Holes>

在我的文档的另一部分中,我想通过它的id引用一个洞。 e.g。

<Drill useHoleWithId='1'/>

当我的代码找到上面的&lt; Drill&gt; element我希望它在&lt; Hole&gt;中检索'dia'和'depth'属性的值id ='1'的元素。

当然我可以搜索&lt; Hole&gt; id等于'useHoleWithId'值的元素,然后获取属性的值,但我想也许有更好的方法来使用一些XML技巧来做到这一点。有吗?

PS - 虽然我对它们一无所知,但可能是XPath,XLink,XQuery或XPointer中的任何一个都可以提供帮助。

4 个答案:

答案 0 :(得分:4)

XPath肯定是一种方法。用于查找ID为1的保留的Xpath查询类似于Holes/Hole[@id="1"]

答案 1 :(得分:3)

有一个标准的XPath函数可以通过“id”属性来引用元素。

来自XPath 1.0规范。:

id() 函数函数按唯一ID选择元素(参见[5.2.1唯一ID])。当id的参数的类型为node-set时,结果是将id应用于参数中每个节点的string-value的结果{ {1}}。当node-set的参数是任何其他类型时,参数将转换为id,就好像通过调用string一样; string function被分为stringwhitespace-separated list of tokens是与作品whitespace匹配的任何字符序列);结果是S包含与node-set相同document的元素,其context node等于列表中的任何标记。

  • unique ID选择具有唯一id("foo") foo的元素

  • ID选择了第五个孩子 具有唯一id("foo")/child::para[position()=5] foo

  • 的元素

XSLT 中可以使用另一种更通用的方式来引用节点(不仅仅是元素)。 <xsl:key/> 指令和XSLT key() 功能专门用于此目的。

例如,假设一个文档包含XSLT形式的书目引用,并且有一个单独的XML文档bib.xml,其中包含一个带有以下形式的条目的书目数据库:

ID

然后样式表可以使用以下内容转换bibref元素

<entry name="XSLT">...</entry>

请注意,XSLT中的键克服了<xsl:key name="bib" match="entry" use="@name"/> <xsl:template match="bibref"> <xsl:variable name="name" select="."/> <xsl:for-each select="document('bib.xml')"> <xsl:apply-templates select="key('bib',$name)"/> </xsl:for-each> </xsl:template> 函数的以下限制:

  • 必须将ID属性声明为 这样在DTD中。如果是ID属性 仅被声明为ID属性 在外部DTD子集中,然后它 将被识别为ID属性 只有XML处理器读取 外部DTD子集。但是,XML 不需要XML处理器 阅读外部DTD,他们可能会 特别是选择不这样做 如果文件被宣布 id()

  • 文档只能包含一个文档 一组唯一ID。不可能 独立的独立集合 的ID。

  • 元素的ID只能是 在属性中指定;这不可以 由内容指定 元素或子元素。

  • ID被限制为XML 名称。例如,它不能包含 空格。

  • 元素最多只能有一个ID。

  • 最多一个元素可以有一个 特别ID。

由于这些限制,XML文档有时包含一个交叉引用结构,该结构未由ID / IDREF / IDREFS属性显式声明。

答案 2 :(得分:1)

XML是对数据的惰性视图。您已经 使用“useHoleWithId”创建了引用。你如何解释和采取行动来获得<hole>元素取决于你的实现,当然xpath(更改文档的xslt只是实现xpath来实现这一点)是一种强有力的方法。

答案 3 :(得分:0)

你可以改变它:

  <xsl:for-each select="my/Drill">
   <xsl:variable name="drillid"> 
    <xsl:value-of select="@useHoleWithId"/>
   </xsl:variable> 
   <Drill>
    <xsl:attribute name="diameter">
     <xsl:value-of select="/my/Holes/Hole[@id=$drillid]/@dia"/>
    </xsl:attribute>
    <xsl:attribute name="useid">
     <xsl:value-of select="$drillid"/>
    </xsl:attribute>
   </Drill>
  </xsl:for-each>

以便Hole的{​​{1}}属性显示在Drill标记