2009-02-10 3 views
4

Я пытаюсь эмулировать поведение StringBuilder в XSL. Есть ли способ сделать это. Это довольно сложно, учитывая тот факт, что XSLT является функциональным языком программирования.Можно ли эмулировать StringBuilder в XSLT?

+0

Что именно вы подразумеваете под "Emulate StringBuilder"? StringBuilder делает несколько вещей, наиболее распространенными из которых являются добавления к строкам, но он также может заменять подстроки, искать подстроку, подсчитывать ее длину и т. Д. Что конкретно вы ищете? Просто добавление? Поиск? Какие? – Welbog

+0

Я ищу только функциональность добавления. –

+0

Невозможно изменить значение переменной в XSLT, как только оно будет определено. Это по определению, потому что XSLT является функциональным языком. Это не означает, что нет быстрых реализаций неизменяемых строк * (даже быстрее, чем строка .NET). Узнайте больше об этом в моем ответе. –

ответ

2

Вы можете получить аккумулирующие конкатеты просто с небольшим количеством рекурсии, если вы смотрите на набор узлов (до тех пор, пока вы можете построить xpath для поиска набора узлов), делая это так, чтобы вы может добавлять произвольные биты и куски в поток и из потока, который начинает становиться беспорядочным.

Попробуйте для начала (это присоединиться, а):

<xsl:template match="/"> 
    <xsl:variable name="s"> 
     <xsl:call-template name="stringbuilder"> 
      <xsl:with-param name="data" select="*" /><!-- your path here --> 
     </xsl:call-template> 
    </xsl:variable> 
    <xsl:value-of select="$s" /><!-- now contains a big concat string --> 
</xsl:template> 

<xsl:template name="stringbuilder"> 
    <xsl:param name="data"/> 
    <xsl:param name="join" select="''"/> 
    <xsl:for-each select="$data/*"> 
     <xsl:choose> 
      <xsl:when test="not(position()=1)"> 
       <xsl:value-of select="concat($join,child::text())"/> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="child::text()"/> 
      </xsl:otherwise> 
     </xsl:choose>  
    </xsl:for-each> 
</xsl:template> 

Всевозможные расширений, которые могут потребоваться: возможно, вы хотите обрезать, возможно, вы хотите, чтобы туннель через иерархии, а также. Я не уверен, что существует пуленепробиваемое общее решение.

+0

Переменная $ join не служит никакой цели. Это сбивает с толку и вводит в заблуждение! Вместо «concat» ($ join, child :: text()) «используйте только« text() ». Целый не нужен. используйте сингл: "xsl: copy-of select = '$ data/text()'" –

+0

Вы действительно особенный тип тролля, разве вы не Dimitre? ОЧЕНЬ ОЧЕНЬ ЧИСТЫЙ параметр соединения является необязательным (см., Где у него есть выбор?), который позволяет строителю функционировать как метод .join (см., где я говорю «действительно присоединяется»?), который требует цикла, который обеспечивает расширение («для стартеров»?). – annakata

+0

@annakata Я полностью не понимаю, что для вас «ОЧЕНЬ ОЧЕНЬ ОЧЕНЬ ОЧЕНЬ». Мне очень любопытно, что это может быть. Можете ли вы объяснить и дать небольшой пример использования параметра «join»? –

4

Посмотрите на функции concat() и string-join(), возможно, это то, что вам нужно.

+0

Я ищу только функциональность добавления. И это означает, что я хочу сохранить результат после добавления в той же переменной –

+0

Нет, это будет невозможно. Переменные неизменяемы в XSLT, вы не можете их изменить. Вы можете использовать рекурсию, чтобы получить аналогичный результат. Что именно вы хотите сделать? Можете ли вы опубликовать код на свой вопрос? – Tomalak

+0

Я думаю, рекурсия может работать здесь. Спасибо всем. –

1

Вы можете использовать все доступные standard XPath 2.0 string functions, такие как concat(), substring(), substring-before(), substring-after(), string-join(), ... и т.д.

Однако в случае, если необходимо очень быстрое внедрение строк (даже быстрее, чем класс .NET string), вы, вероятно, будете интересоваться C# implementationfinger-tree data structure и the extension functions I provided для Saxon XSLT-процессора, которые обертывают строку на основе пальца.

Смежные вопросы