2012-05-20 2 views
3

В моем преобразовании XSLT у меня есть две строки анализа, которые мне нужно использовать для обработки одного узла. Они работают отлично один за другим, но я не знаю, как их собрать.Как использовать две разные аналитические строки для одного узла

XML документ выглядит следующим образом:

<article> 
    <title>Article 1</title> 
    <text><![CDATA[Lorem ipsum dolor sit amet, s consectetur adipiscing elit. Donec lorem diam, eleifend sed mollis id, condimentum in velit. 

Sed sit amet erat ac mauris adipiscing elementum. Pellentesque eget quam augue, id faucibus magna. 

Ut malesuada arcu eu elit sodales sodales. Morbi tristique porttitor tristique. Praesent eget vulputate dui. Cras ut tortor massa, at faucibus ligula.]]></text> 
</article> 

Вот мой XSLT:

<xsl:template match="/"> 
    <html> 
     <head> 
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> 
      <title>Page title</title> 
     </head> 
     <body> 
      <xsl:for-each select="article"> 
       <h1><xsl:value-of select="./title"/></h1> 

       <!-- This adds paragraphs tags instead of empty lines in the text --> 
       <xsl:analyze-string select="./text" regex="&#xa;"> 
        <xsl:non-matching-substring> 
         <p> 
          <xsl:value-of select="." disable-output-escaping="yes"/> 
         </p> 
        </xsl:non-matching-substring> 
       </xsl:analyze-string> 

       <!-- This is Czech language specific. It looks for ' s ' (or other letter) and changes second space for &nbsp;. So after that it is ' s&nbsp;'. --> 
       <xsl:analyze-string select="./text" regex="(\s[k/K/s/S/v/V/z/Z]\s)"> 
        <xsl:matching-substring> 
         <xsl:text> </xsl:text> 
         <xsl:value-of select="replace(., ' ','')" disable-output-escaping="yes"/> 
         <xsl:text disable-output-escaping="yes"><![CDATA[&nbsp;]]></xsl:text> 
        </xsl:matching-substring> 
        <xsl:non-matching-substring> 
         <xsl:value-of select="." disable-output-escaping="yes"/> 
        </xsl:non-matching-substring> 
       </xsl:analyze-string> 
      </xsl:for-each> 
     </body> 
    </html> 
</xsl:template> 

мне нужно применить и проанализировать-строк на генерируемый текст таким образом, есть <p> теги для пунктов, а также добавил, &nbsp; в нужных местах.

Мой желаемый результат будет выглядеть следующим образом:

<h1>Article 1</h1>  
<p>Lorem ipsum dolor sit amet, s&nbsp;consectetur adipiscing elit. Donec lorem diam, eleifend sed mollis id, condimentum in velit.</p> 
<p>Sed sit amet erat ac mauris adipiscing elementum. Pellentesque eget quam augue, id faucibus magna.</p> 
<p>Ut malesuada arcu eu elit sodales sodales. Morbi tristique porttitor tristique. Praesent eget vulputate dui. Cras ut tortor massa, at faucibus ligula.</p> 

Любая идея, как это сделать? Спасибо, что нашли время и пытались мне помочь.

+0

Вы забыли предоставить исходный XML-документ. Пожалуйста, отредактируйте вопрос и предоставьте это. –

+0

Пояснения искали. Пожалуйста, см. Раздел примечаний в моем ответе. –

ответ

3

Вот моя настройка на решение Димитрия:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="html" indent="yes" encoding="UTF-8"/> 

<xsl:template match="/*/text"> 
    <xsl:for-each select="tokenize(replace(., '\s([kKsSvVzZ])\s', ' $1&#xA0;'), '\n')"> 
    <p><xsl:value-of select="."/></p> 
    </xsl:for-each> 
</xsl:template> 

<xsl:template match="title"> 
    <h1><xsl:value-of select="."/></h1> 
</xsl:template> 
</xsl:stylesheet> 

Примечания

  1. Я не уверен, что вы имеете в виду под "буквы S/S/v/V/K/K/Z/Z". Это недопустимое регулярное выражение. Вам нужно уточнить. Я предположил, что вы имели в виду класс символов [sSvVkKzZ]
  2. Хотя неясно, ссылка на чешский язык предполагает, что UTF-8 может быть лучшим выбором для кодировки вывода, а не для ASCII.
  3. Хотя неясно, ожидаемые выходные теги предполагают, что более подходящая сериализация будет html.
  4. В качестве побочного преимущества выбора сериализации html нам больше не нужна карта символов, что упрощает наше решение. Мы можем использовать встроенную карту символов для сериализации html.
  5. Использование fn: tokenise() устраняет необходимость в узлах xsl: analysis-string/xsl: non-matching-substring, что, возможно, приводит к более жесткому решению.
  6. Это решение было протестировано с саксоном.
  7. Возможны варианты. Например, вы можете переместить вызов replace() в значение xsl: значение, которое вы можете считать более доступным для чтения.
  8. Недостатком моего решения является то, что он не работает с отключением-выходом-экранированием = «да». Однако я предлагаю, чтобы, если вы считаете, что вам это нужно, пожалуйста, внимательно посмотрите на причины. Любой HTML-код нуждается в безопасном HTML-кодировании, если он не находится внутри раздела CDATA. Есть что-то не так с идеей генерации HTML с включенным отключением вывода. Возможно, я не совсем понял этот вопрос. Не могли бы вы привести пример использования, который разъясняет суть?
3

Это преобразование:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes" encoding="ascii"/> 

<xsl:template match="/*/text"> 
    <xsl:analyze-string select= 
    "replace(., '\ss\s', ' s&#xA0;')" 
    regex="&#xA;"> 
    <xsl:non-matching-substring> 
    <p><xsl:sequence select="."/></p> 
    </xsl:non-matching-substring> 
    </xsl:analyze-string> 
</xsl:template> 

<xsl:template match="title"> 
    <h1><xsl:value-of select="."/></h1> 
</xsl:template> 
</xsl:stylesheet> 

При нанесении на предоставленном документе XML:

<article> 
    <title>Article 1</title> 
<text><![CDATA[Lorem ipsum dolor sit amet, s consectetur adipiscing elit. Donec lorem diam, eleifend sed mollis id, condimentum in velit. 
Sed sit amet erat ac mauris adipiscing elementum. Pellentesque eget quam augue, id faucibus magna. 
Ut malesuada arcu eu elit sodales sodales. Morbi tristique porttitor tristique. Praesent eget vulputate dui. Cras ut tortor massa, at faucibus ligula.]]></text> 
</article> 

производит разыскиваемый, правильный результат:

<h1>Article 1</h1> 
<p>Lorem ipsum dolor sit amet, s&#160;consectetur adipiscing elit. Donec lorem diam, eleifend sed mollis id, condimentum in velit.</p> 
<p>Sed sit amet erat ac mauris adipiscing elementum. Pellentesque eget quam augue, id faucibus magna.</p> 
<p>Ut malesuada arcu eu elit sodales sodales. Morbi tristique porttitor tristique. Praesent eget vulputate dui. Cras ut tortor massa, at faucibus ligula.</p> 

Примечание: Программистам не рекомендуется использовать DOE, поскольку это не обязательная функция XSLT 2.0, и нет никаких гарантий, что любой процессор XSLT 2.0 может поддерживать DOE. Вместо этого используется функция character maps.

Тогда вся трансформация становится:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes" 
    encoding="ascii" use-character-maps="nbsp"/> 

<xsl:character-map name="nbsp"> 
    <xsl:output-character 
    character="&#xA0;" string="&amp;nbsp;"/> 
</xsl:character-map> 

<xsl:template match="/*/text"> 
    <xsl:analyze-string select= 
    "replace(., '\ss\s', ' s&#xA0;')" 
    regex="&#xA;"> 
    <xsl:non-matching-substring> 
    <p><xsl:sequence select="."/></p> 
    </xsl:non-matching-substring> 
    </xsl:analyze-string> 
</xsl:template> 

<xsl:template match="title"> 
    <h1><xsl:value-of select="."/></h1> 
</xsl:template> 
</xsl:stylesheet> 

и при нанесении на документ же XML (выше), он производит разыскиваемого, правильный результат:

<h1>Article 1</h1> 
<p>Lorem ipsum dolor sit amet, s&nbsp;consectetur adipiscing elit. Donec lorem diam, eleifend sed mollis id, condimentum in velit.</p> 
<p>Sed sit amet erat ac mauris adipiscing elementum. Pellentesque eget quam augue, id faucibus magna.</p> 
<p>Ut malesuada arcu eu elit sodales sodales. Morbi tristique porttitor tristique. Praesent eget vulputate dui. Cras ut tortor massa, at faucibus ligula.</p> 
+0

Спасибо, Димитрий, у меня еще два вопроса. Мне нужно добавить nbsp; после всех букв s/S/v/V/k/K/z/Z ваше преобразование добавляет его только после 's'. Как настроить его в соответствии с моими потребностями лучше? Мне также нужно включить disable-output-escaping = "yes" для текстового элемента. Это для гиперссылок в тексте. Как я могу это сделать, пожалуйста? – johnnym26

+0

@ johnnym26: Добро пожаловать. Я просто проснулся утром, так что вы ждали ответа более 6 часов - извините за разницу во времени. Это решение было просто для того, чтобы дать вам пример того, как решить проблему. Я не знаю CZech, поэтому я не пытался делать «s/S/v/V/k/K/z/Z», что не было объяснено в вопросе. Что касается DOE, я настоятельно рекомендую избегать этого как можно больше. Посмотрите, не приведет ли сериализация к методу 'htm'l нужной сериализации. –

2

Вы не сделали это очень ясно, но моя интерпретация вопроса заключалась в том, что вы хотели использовать вторую xsl: analy-string для обработки вывода первого. Вы можете сделать это, поместив результат первого в переменную, но моя рекомендация будет поместить каждый вызов xsl: analy-string в тело функции и составить их с использованием композиции функций.

<xsl:function name="f:one" as="xs:string"> 
    <xsl:param name="in" as="xs:string"> 
    <xsl:analyze-string select="in".../> 
</xsl:function> 

<xsl:function name="f:two" as="xs:string"> 
    <xsl:param name="in" as="xs:string"> 
    <xsl:analyze-string select="in".../> 
</xsl:function> 

... select="f:two(f:one(.))"... 

Однако в вашем случае это проще, так как первый XSL: анализ-нить можно сделать с помощью простого вызова на замену().

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