Ссылка на другой элемент в XML - PullRequest
4 голосов
/ 21 января 2009

Я пытаюсь разработать структуру документа 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>

В другой части моего документа я хочу сослаться на дыру по ее идентификатору. например,

<Drill useHoleWithId='1'/>

Когда мой код находит выше элемент, я хочу, чтобы он извлекал значения атрибутов 'dia' и 'deep' в элементе , который имеет id = '1'.

Конечно, я могу найти элемент с идентификатором, равным значению 'useHoleWithId', а затем получить значения атрибутов, но я подумал, что, возможно, есть лучший способ сделать это с помощью некоторого трюка XML. Есть ли?

PS - Хотя я понятия не имею о них, может быть, любой из XPath, XLink, XQuery или XPointer может помочь.

Ответы [ 4 ]

4 голосов
/ 21 января 2009

XPath, безусловно, является одним из способов сделать это. Запрос Xpath для определения удержания с идентификатором 1 будет выглядеть примерно так: Holes/Hole[@id="1"]

3 голосов
/ 21 января 2009

Существует стандартная функция XPath для ссылки на элементы по их атрибуту "id" .

Из XPath 1.0 spec .:

Функция id() выбирает элементы по их уникальным ID (см. [5.2.1 Уникальные идентификаторы]). Если аргумент id имеет тип node-set, то результатом является объединение результата применения id к string-value каждого из узлов в аргументе node-set. Когда аргумент id относится к какому-либо другому типу, аргумент преобразуется в string, как будто путем вызова string function; string делится на whitespace-separated list of tokens (whitespace - любая последовательность символов, соответствующая производной S); В результате получается node-set, содержащий элементы в том же document, что и context node, которые имеют unique ID, равный любому из токенов в списке.

  • id("foo") выделяет элемент с уникальным ID foo

  • id("foo")/child::para[position()=5] выбирает пятого абзаца потомка
    элемент с уникальным ID foo

Другой, более общий способ ссылки на узлы (не только элементы) возможен в XSLT . Инструкция <xsl:key/> и функция XSLT key() специально разработаны для этой цели.

Например, , предположим, что документ содержит библиографические ссылки в форме XSLT, и существует отдельный документ XML bib.xml, содержащий библиографическую базу данных с записями в форме:

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

Тогда таблица стилей может использовать следующее для преобразования элементов bibref :

<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>

Обратите внимание , что ключи в XSLT преодолевают следующие ограничения функции id():

  • Атрибуты идентификатора должны быть объявлены как такой в ​​DTD. Если идентификатор атрибута объявляется только как атрибут ID во внешнем подмножестве DTD, то это будет распознан как атрибут ID только если процессор XML читает внешнее подмножество DTD. Тем не менее, XML не требует, чтобы процессоры XML читать внешние DTD, и они могут хорошо, чтобы не делать этого, особенно если документ объявлен standalone="yes".

  • Документ может содержать только один набор уникальных идентификаторов. Там не может быть отдельные независимые наборы уникальных Идентификаторы.

  • Идентификатор элемента может быть только указывается в атрибуте; это не может быть определено содержанием элементом или дочерним элементом.

  • Идентификатор должен быть XML название. Например, он не может содержать пространства.

  • Элемент может иметь не более одного идентификатора.

  • Максимум один элемент может иметь конкретный ID.

Из-за этих ограничений XML-документы иногда содержат структуру перекрестных ссылок, которая явно не объявлена ​​атрибутами ID / IDREF / IDREFS.

1 голос
/ 21 января 2009

XML - инертное представление данных. Вы уже создали ссылку с помощью useHoleWithId. То, как вы интерпретируете и действуете так, чтобы получить элемент <hole>, зависит от вашей реализации, и, безусловно, xpath (xslt для изменения документа просто реализует xpath для этого) - это надежный способ сделать это.

0 голосов
/ 21 января 2009

Вы можете преобразовать это:

  <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 отображался в Drill тегах

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...