Написание запроса XPath для сопоставления элементов на основе атрибутов и содержимого - PullRequest
4 голосов
/ 19 февраля 2010

У меня есть такой XML-код:

<topics>
  <topic id="50"/>
  <topic id="51"/>
  <topic id="52"/>
</topics>

<discussions>
  <discussion type="foo">talked about T50 as Discussion 1000</discussion>
  <discussion type="bar">Food is yummy!</discussion>
  <discussion type="foo">talked about T52 as Discussion 1050</discussion>
</discussions>

Учитывая идентификатор конкретной темы ($topicID), я хотел бы сделать следующее:

  • Разработайте выражение XPath, которое истинно, если существует <discussion> с type="foo", содержащим текст T$topicID as Discussion <corresponding-discussion-id>.

  • Разработайте выражение XPath, которое, учитывая, что $topicIDизвлечет текст Discussion <corresponding-discussion-id>.

Возможно ли это?

Обновление:

Для первого, я думаю, мне нужно что-то вроде:

exists(
 //discussions/discussion[
  @type="foo" and
  contains(text(), concat($topicId, ??? ))  <-- What goes here? I think we need
 ]                                           some kind of matches(...) around the
)                                            concat(), too.

Ответы [ 2 ]

5 голосов
/ 19 февраля 2010

Следующий XPath выберет атрибут обсуждения тип = = foo и содержащий текст «Обсуждение как T50» (когда $ topicid = 50).

//discussions/discusson[@type='foo' and contains(., concat('T', $topicid, ' as Discussion ')]

Для конкретного элемента обсуждения соответствующийидентификатор задается как:

substring-after(normalize-space(.),' as Discussion ')

Мы можем объединить 2, заменив "."во втором выражении со всем первым выражением.Обратите внимание, что если несколько обсуждений соответствуют внутреннему выражению, мы сопоставим их значения со вторым.

substring-after(normalize-space(
    //discussions/discusson[@type='foo' and contains(., concat('T', $topicid, ' as Discussion ')]
),' as Discussion ')

Если было несколько совпадающих обсуждений, вы можете обработать их следующим образом:

<xsl:for-each select="//topics/topic">
    <xsl:variable name="topicid" select="@id" />
    <xsl:for-each select="//discussions/discusson[@type='foo' and contains(., concat('T', $topicid, ' as Discussion ')]">
        <xsl:variable name="relatedid" select="substring-after(normalize-space(.),' as Discussion ')" />

        <!-- do something with $topicid and $relatedid -->

    </xsl:for-each>
</xsl:for-each>

Ссылки на функции:

Лично я не могу себе представить серьезную разработку XSLT без книги Майкла Кея.

1 голос
/ 19 февраля 2010

Содержит ли обсуждение type=foo соответствующее topicID:

/discussions/discussion[@type=foo AND contains(.,'T52')]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...