Соответствовать условно текущему значению узла - PullRequest
8 голосов
/ 15 сентября 2008

С учетом следующего XML:

<current>
  <login_name>jd</login_name>
</current>
<people>
  <person>
    <first>John</first>
    <last>Doe</last>
    <login_name>jd</login_name>
  </preson>
  <person>
    <first>Pierre</first>
    <last>Spring</last>
    <login_name>ps</login_name>
  </preson>
</people>

Как я могу получить "John Doe" из текущего / входного сопоставления?

Я попробовал следующее:

<xsl:template match="current/login_name">
  <xsl:value-of select="../people/first[login_name = .]"/>
  <xsl:text> </xsl:text>
  <xsl:value-of select="../people/last[login_name = .]"/>
</xsl:template>

Ответы [ 5 ]

10 голосов
/ 15 сентября 2008

Я бы определил ключ для индексации людей:

<xsl:key name="people" match="person" use="login_name" />

Использование ключа здесь просто обеспечивает чистоту кода, но вы также можете найти его полезным для эффективности, если вам часто приходится извлекать элементы <person> на основе их <login_name> дочернего элемента.

У меня был бы шаблон, который возвращал бы отформатированное имя данного <person>:

<xsl:template match="person" mode="name">
  <xsl:value-of select="concat(first, ' ', last)" />
</xsl:template>

А потом я бы сделал:

<xsl:template match="current/login_name">
  <xsl:apply-templates select="key('people', .)" mode="name" />
</xsl:template>
4 голосов
/ 15 сентября 2008

Вы хотите current() функция

<xsl:template match="current/login_name">
  <xsl:value-of select="../../people/person[login_name = current()]/first"/>
  <xsl:text> </xsl:text>
  <xsl:value-of select="../../people/person[login_name = current()]/last"/>
</xsl:template>

или чуть чище:

<xsl:template match="current/login_name">
  <xsl:for-each select="../../people/person[login_name = current()]">
    <xsl:value-of select="first"/>
    <xsl:text> </xsl:text>
    <xsl:value-of select="last"/>
  </xsl:for-each>
</xsl:template>
1 голос
/ 17 сентября 2008

Если вам нужно получить доступ к нескольким пользователям, то подход JeniT <xsl:key /> идеален.

Вот мой альтернативный вариант:

<xsl:template match="current/login_name">
    <xsl:variable name="person" select="//people/person[login_name = .]" />
    <xsl:value-of select="concat($person/first, ' ', $person/last)" />
</xsl:template>

Мы присваиваем выбранный узел <person> переменной, затем используем функцию concat() для вывода имени / фамилии.

В вашем примере XML также есть ошибка. Узел <person> неверно оканчивается на </preson> (опечатка)

Лучшее решение могло бы быть дано, если бы мы знали общую структуру документа XML (с корневыми узлами и т. Д.)

0 голосов
/ 15 сентября 2008

Просто чтобы добавить свои мысли в стек

<xsl:template match="login_name[parent::current]">
 <xsl:variable name="login" select="text()"/>
 <xsl:value-of select='concat(ancestor::people/child::person[login_name=$login]/child::first/text()," ",ancestor::people/child::person[login_name=$login]/child::last/text())'/>
</xsl:template>

Я всегда предпочитаю использовать оси явно в моем XPath, более подробный, но более понятный ИМХО.

В зависимости от того, как выглядят остальные XML-документы (при условии, что это всего лишь фрагмент), вам может понадобиться ограничить ссылку на «ancestor :: people», например, используя «ancestor :: people [1]», чтобы ограничить предок первых людей.

0 голосов
/ 15 сентября 2008

Я думаю, что он на самом деле хотел, чтобы замена в совпадении для "текущего" узла, а не совпадение в узле человека:

<xsl:variable name="login" select="//current/login_name/text()"/>

<xsl:template match="current/login_name">
<xsl:value-of select='concat(../../people/person[login_name=$login]/first," ", ../../people/person[login_name=$login]/last)'/>

</xsl:template>
...