Замените символ новой строки на ‹br /› XSL

У меня есть список Sharepoint, который я хочу преобразовать в JSON через представление данных XSL.

У меня есть функция рекурсивной замены XSL, которую я использую для замены всех специальных символов (обратная косая черта, двойные кавычки и т. д.), что дает мне хороший чистый JSON, который правильно анализируется в браузере пользователей.

Последнее, что мне нужно скрыть/заменить, это новая строка char. Новая строка вызывает ошибки при анализе JSON в некоторых браузерах.

Вот некоторый xsl, который проверяет, есть ли в содержимом заголовка новая строка char, если это так, мы выводим абзац:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">

    <xsl:for-each select="catalog/cd">

        <xsl:if test='contains(title,"&#xA;")'>   
                <p>Found <xsl:value-of select="title" /></p>
        </xsl:if>

    </xsl:for-each>

</xsl:template>
</xsl:stylesheet>

Вот пример xml:

<catalog>
    <cd>
        <title>Empire 
Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
    <cd>
        <title>Hide your heart</title>
        <artist>Bonnie Tyler</artist>
        <country>UK</country>
        <company>CBS Records</company>
        <price>9.90</price>
        <year>1988</year>
    </cd>
    <cd>
        <title>Greatest Hits</title>
        <artist>Dolly Parton</artist>
        <country>USA</country>
        <company>RCA</company>
        <price>9.90</price>
        <year>1982</year>
    </cd>
</catalog>

"Empire Burlesque" должен быть единственным элементом, прошедшим проверку, но все три названия проходят проверку if и выводятся.

ИЗМЕНИТЬ

Изменяя приведенное ниже решение, я предполагаю, что это должно работать, если я хочу выполнить поиск и замену на основе отдельного узла? Я не смогу протестировать его в Sharepoint до завтра.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/">
  <xsl:for-each select="catalog/cd">

  <xsl:variable name="title_clean">
    <xsl:call-template name="repNL">
      <xsl:with-param name="pText" select="title"/>
    </xsl:call-template>
  </xsl:variable>

  <p><xsl:value-of select='$title_clean' /></p>

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


<xsl:template name="repNL">
  <xsl:param name="pText" select="."/>

  <xsl:copy-of select="substring-before(concat($pText,'&#xA;'),'&#xA;')"/>

  <xsl:if test="contains($pText, '&#xA;')">
  <br />
  <xsl:call-template name="repNL">
  <xsl:with-param name="pText" select=
  "substring-after($pText, '&#xA;')"/>
  </xsl:call-template>
  </xsl:if>
</xsl:template>

</xsl:stylesheet>

person Fergal    schedule 15.05.2011    source источник
comment
Похоже на дубликат: stackoverflow.com/questions/3309746   -  person mzjn    schedule 15.05.2011
comment
Невозможно воспроизвести предоставленные входные данные. Для примера XML и вашего примера XSLT он соответствует только заголовку Empire Burlesque. Я не получаю все три названия на выходе. Вы уверены, что пример XML соответствует вашим фактическим данным?   -  person Mads Hansen    schedule 15.05.2011
comment
Хороший вопрос, +1. Смотрите мой ответ для полного, краткого и простого решения и для подробного объяснения.   -  person Dimitre Novatchev    schedule 15.05.2011
comment
результаты могут быть воспроизведены на w3schools.com/xsl/   -  person Fergal    schedule 15.05.2011


Ответы (2)


"Empire Burlesque" должен быть единственным элементом, прошедшим проверку, но все три названия проходят проверку if и выводятся.

Не удается воспроизвести заявленную проблему – протестировано с 9 различными процессорами XSLT, включая все процессоры Microsoft.

Так или иначе:

Это преобразование заменяет любой символ NL в текстовом узле элементом br:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="text()" name="repNL">
  <xsl:param name="pText" select="."/>

  <xsl:copy-of select=
  "substring-before(concat($pText,'&#xA;'),'&#xA;')"/>

  <xsl:if test="contains($pText, '&#xA;')">
   <br />
   <xsl:call-template name="repNL">
    <xsl:with-param name="pText" select=
    "substring-after($pText, '&#xA;')"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

при применении к следующему XML-документу (предоставленный с добавленным cd, чтобы сделать его более интересным):

<catalog>
    <cd>
        <title>Line1
        Line2
        Line3
        </title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
    <cd>
        <title>Empire
        Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
    <cd>
        <title>Hide your heart</title>
        <artist>Bonnie Tyler</artist>
        <country>UK</country>
        <company>CBS Records</company>
        <price>9.90</price>
        <year>1988</year>
    </cd>
    <cd>
        <title>Greatest Hits</title>
        <artist>Dolly Parton</artist>
        <country>USA</country>
        <company>RCA</company>
        <price>9.90</price>
        <year>1982</year>
    </cd>
</catalog>

получен желаемый правильный результат:

<catalog>
   <cd>
      <title>Line1<br/>     Line2<br/>      Line3<br/>      
      </title>
      <artist>Bob Dylan</artist>
      <country>USA</country>
      <company>Columbia</company>
      <price>10.90</price>
      <year>1985</year>
   </cd>
   <cd>
      <title>Empire<br/>        Burlesque</title>
      <artist>Bob Dylan</artist>
      <country>USA</country>
      <company>Columbia</company>
      <price>10.90</price>
      <year>1985</year>
   </cd>
   <cd>
      <title>Hide your heart</title>
      <artist>Bonnie Tyler</artist>
      <country>UK</country>
      <company>CBS Records</company>
      <price>9.90</price>
      <year>1988</year>
   </cd>
   <cd>
      <title>Greatest Hits</title>
      <artist>Dolly Parton</artist>
      <country>USA</country>
      <company>RCA</company>
      <price>9.90</price>
      <year>1982</year>
   </cd>
</catalog>

Пояснение:

  1. Правило/шаблон идентификации копирует каждый узел "как есть".

  2. Переопределяющий шаблон, который соответствует любому текстовому узлу (также называемому "repNL"), выполняет следующую обработку:

  3. Используя метку (символ NL, добавленный к строке), подстрока перед первым символом NL (или вся строка, если символ NL не содержится) копируется в выходной файл.

  4. Если символ NL действительно содержится, то генерируется элемент br, и шаблон рекурсивно вызывает себя для оставшейся строки после этого символа NL.

person Dimitre Novatchev    schedule 15.05.2011

Если вы используете XslCompiledTransform(C#), я полагаю, что вы столкнетесь с проблемой, если будете использовать приведенный ниже API для преобразования XML:
XslCompiledTransform.Transform(XmlReader input, XmlWriter results)

Однако приведенный ниже API работает хорошо:
XslCompiledTransform.Transform(string, string);
Это зашито, но я не понимаю, почему...

person sky    schedule 13.02.2015