Обрезать пробелы только из родительского элемента - PullRequest
2 голосов
/ 22 октября 2010

Я бы хотел обрезать начальные пробелы внутри p-тегов в XML, так что это:

<p>  Hey, <em>italics</em> and <em>italics</em>!</p>

Получается так:

<p>Hey, <em>italics</em> and <em>italics</em>!</p>

(Обрезка конечных пробелов не повредит, но это не обязательно.)

Теперь я знаю, normalize-whitespace() должен это делать, но если я попытаюсь применить его к текстовым узлам ..

<xsl:template match="text()">
  <xsl:text>[</xsl:text>
  <xsl:value-of select="normalize-space(.)"/>
  <xsl:text>]</xsl:text>
</xsl:template>

...it применяется к каждому текстовому узлу (в скобках) индивидуально и высасывает их всухую:

[Hey,]<em>[italics]</em>[and]<em>[italics]</em>[!]

Мой XSLT выглядит в основном так:

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

Так есть ли способ, которым я могу позволитьapply-templates complete и затем запустят normalize-space на выходе, что должно сделать правильно?

Ответы [ 3 ]

5 голосов
/ 22 октября 2010

Эта таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="p//text()[1][generate-id()=
                                      generate-id(ancestor::p[1]
                                                  /descendant::text()[1])]">
        <xsl:variable name="vFirstNotSpace"
                      select="substring(normalize-space(),1,1)"/>
        <xsl:value-of select="concat($vFirstNotSpace,
                                     substring-after(.,$vFirstNotSpace))"/>
    </xsl:template>
</xsl:stylesheet>

Вывод:

<p>Hey, <em>italics</em> and <em>italics</em>!</p>

Редактировать 2 : лучшее выражение (теперь только три вызова функций).

Редактировать 3 : Соответствует первому текстовому узлу-потомку (не только первому узлу, если это текстовый узел).Благодаря комментарию @ Dimitre.

Теперь с этим входом:

<p><b>  Hey, </b><em>italics</em> and <em>italics</em>!</p>

Вывод:

<p><b>Hey, </b><em>italics</em> and <em>italics</em>!</p>
4 голосов
/ 22 октября 2010

Я бы сделал что-то вроде этого:

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

<!-- strip leading whitespace -->
<xsl:template match="p/node()[1][self::text()]">
  <xsl:call-template name="left-trim">
     <xsl:with-param name="s" value="."/>
  </xsl:call-template>
</xsl:template>

Это уберет левое пространство от начального дочернего узла элемента <p>, если это текстовый узел.Он не будет очищать пространство от первого дочернего узла текста, если это не первый дочерний узел.Например,

<p><em>Hey</em> there</p>

Я намеренно стараюсь не убирать пробел в начале «там», потому что это приведет к тому, что слова будут отображаться вместе при визуализации в браузере.Если вы хотите удалить этот пробел, измените шаблон соответствия на

match="p/text()[1]"

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

<!-- strip trailing whitespace -->
<xsl:template match="p/node()[last()][self::text()]">
  <xsl:call-template name="right-trim">
     <xsl:with-param name="s" value="."/>
  </xsl:call-template>
</xsl:template>

<!-- strip leading/trailing whitespace on sole text node -->
<xsl:template match="p/node()[position() = 1 and
                              position() = last()][self::text()]"
              priority="2">
   <xsl:value-of select="normalize-space(.)"/>
</xsl:template>

Определения шаблонов обрезки слева и справа приведены в Шаблон обрезки для XSLT (не проверено).Они могут быть медленными для документов с большим количеством <p> с.Если вы можете использовать XSLT 2.0, вы можете заменить шаблоны вызовов на

  <xsl:value-of select="replace(.,'^\s+','')" />

и

  <xsl:value-of select="replace(.,'\s+$','')" />

(благодаря Priscilla Walmsley .)

2 голосов
/ 22 октября 2010

Вы хотите :

 <xsl:template match="text()">
  <xsl:value-of select=
   "substring(
       substring(normalize-space(concat('[',.,']')),2),
       1,
       string-length(.)
              )"/>
 </xsl:template>

Это переносит строку в "[]", затем выполняет normalize-string(), а затем, наконец, удаляет символы переноса.

...