Как заменить имя узла другим в Xslt? - PullRequest
3 голосов
/ 18 декабря 2009

Плохая формулировка вопроса, извините за это. Постараюсь объяснить, что я пытаюсь сделать. По сути, у меня есть результат поиска в виде Xml, и в этом Xml есть такой узел:

<FIELD NAME="body">
  Somebody named 
  <key>Doris</key> 
  and 
  <key>Arnie</key> 
</FIELD>

Короче говоря, мне нужно заменить "" на ""; то есть. выделите результаты поиска (ключевые значения узла - это то, что пользователь искал). В Xslt я не знаю, что искал пользователь, кроме запроса Xml-> FIELD [@ name = 'body'] / key.

Прямо сейчас у меня есть какой-то сумасшедший код, который будет извлекать все, что находится перед поисковым термином («Дорис»), но он работает только для одного поискового запроса. Нам нужно это сделать для нескольких терминов. Код, который мы используем, выглядит следующим образом:

  <xsl:template name="highlighter">
    <xsl:param name="text"/>
    <xsl:param name="what"/>

    <xsl:choose>
      <xsl:when test="contains($text, $what) and string-length($what) &gt; 0">
        <xsl:variable name="before" select="substring-before($text, $what)"/>
        <xsl:variable name="after" select="substring-after($text, $what)"/>
        <xsl:variable name="real-before" select="substring($text, 1, string-length($before))"/>
        <xsl:variable name="real-what" select="substring($text, string-length($before) + 1, string-length($what))"/>
        <xsl:variable name="real-after" select="substring($text, string-length($before) + string-length($what) + 1)"/>
        <xsl:value-of select="$real-before"/>

        <strong>
          <xsl:value-of select="$real-what"/>
        </strong>

        <xsl:call-template name="highlighter">
          <xsl:with-param name="text" select="$real-after"/>
          <xsl:with-param name="what" select="$what"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$text"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

То, что я пытался сделать, - это вызывать этот код несколько раз с разными поисковыми терминами, но я пытаюсь понять, как использовать выходные данные вызова в шаблоне в качестве входных данных для следующего вызова. В коде это будет примерно так:

string body = doc.SelectSingleNode("FIELD[@NAME='body']");
NodeCollection nodes = doc.SelectNodes("FIELD[@NAME='body']/key");
foreach (var node in nodes) {
    body = hightlighter(body, node.InnerText);   
}

До сих пор я не мог сделать что-то подобное в XSLT, но я все еще новичок, так что ...;)

Редактировать: просто чтобы уточнить; вывод, который я ищу, это:

Somebody named <strong>Doris</strong> and <strong>Arnie</strong>

Ответы [ 3 ]

10 голосов
/ 18 декабря 2009

Лучшее, что можно сделать в таких ситуациях, - это рекурсивно копировать узлы из ввода в вывод и переопределять узлы, которые вы хотите обрабатывать по-разному. Основная идея заключается в том, что текстовые строки - это узлы, которые тоже можно копировать. Вот пример:

<xsl:template match="key">
    <strong>
        <xsl:apply-templates select="@*|node()"/>
    </strong>
</xsl:template>

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>
2 голосов
/ 18 декабря 2009

Это должно делать то, что вам нужно. Он использует шаблон применения вместо вызова шаблонов и является более функциональным способом решения этой проблемы.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <!-- Template to match your 'key' and replace with strong -->
    <xsl:template match="FIELD[@name='body']/key">
        <strong><xsl:apply-templates select="@*|node()"/></strong>
    </xsl:template>

    <!-- Template to match all nodes, copy them and then apply templates to children. -->
    <xsl:template match="@*|node()">
      <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
    </xsl:template>
</xsl:stylesheet>
1 голос
/ 18 декабря 2009

Почему нельзя просто заменить элемент "КЛЮЧ" на элементы "СИЛЬНЫЙ"? Лучше не думать об этом слишком настоятельно.

<xsl:template match="FIELD[@NAME='body']">
  <xsl:apply-templates/>
<xsl:template>

<xsl:template match="key">
  <strong>
  <xsl:apply-templates/>
  <strong>
</xsl:template>

<xsl:template match="text()">
  <xsl:copy-of select="."/>
</xsl:template>

Или я вас неправильно понял?

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