Проверьте CR или LF в XSLT - PullRequest
0 голосов
/ 13 марта 2012

У меня есть входной XML, подобный этому:

<in_xml>
 <company>
  <project>
    ProjNo1
    ProjNo2
    ProjNo3
  </project>
 </company>
</in_xml>

Простой XSLT применяется к этому источнику, который записывает другой XML со значением Project Tag.Тег Project во входном xml имеет три строки, это может быть одна или несколько строк.Я ищу способ для XSLT читать только первую строку, если их больше одного, и записать первую строку в выходной xml.Текущий XSLT очень прост, поскольку он просто читает тег Project и выплевывает значение, поэтому код не прикреплен.

С уважением.

Я добавил ответ на вопрос, см.ниже @ ответ маэстро.

Ответы [ 3 ]

3 голосов
/ 13 марта 2012

Если вы счастливы в возможности применения XSLT 2.0, может помочь следующее:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:template match="//project/text()">
        <xsl:value-of select="tokenize(normalize-space(.),' ')[1]" />
    </xsl:template>
</xsl:stylesheet>

Объяснение: сначала normalize-space() заменить все строки пробелов на один пробел (и вырезатьот начального и конечного пробелов), затем разбить на слова, затем взять первый.

В XSLT 1.0 вы могли бы использовать

<xsl:value-of select="substring-before(normalize-space(.), ' ')"/>

.Менее гибкий, если второе слово должно быть выбрано, но для первого слова оно работает ОК.

РЕДАКТИРОВАТЬ

вы спросили, как получить первую строку в XSLT 1.0- проблема в том, что здесь есть пробел в начале, который может содержать LF, поэтому вы не можете просто вставить подстроку перед первым LF.
Возможно, что приведенное ниже может быть улучшено, но он прекрасно работает:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:template match="//project/text()">
        <xsl:variable name="afterLeadingWS"
select="substring-after(., substring-before(.,substring-before(normalize-space(.), ' ')))"/>
        <xsl:choose>
            <xsl:when test="contains($afterLeadingWS, '&#xA;')">
                 <xsl:value-of select="substring-before($afterLeadingWS, '&#xA;')"/>
            </xsl:when>
            <xsl:otherwise>
                 <xsl:value-of select="$afterLeadingWS"/>
            </xsl:otherwise>
        </xsl:choose>
   </xsl:template>
</xsl:stylesheet>

Объяснение:сначала получите первое слово, как и прежде, затем определите пробел перед этим первым словом, затем получите все после этого начального пробела, затем получите первую строку, которая является строкой перед символом LF.Может случиться так, что LF отсутствует, кроме, возможно, в начальном пробеле, отсюда и функция выбора.

0 голосов
/ 15 марта 2012

Снова код, теперь с функцией getFirstLine.
Обратите внимание на дополнительное пространство имен, которое необходимо.
Также обратите внимание, что для этого требуется XSLT 2.0 (xsl: функция недоступна в 1.0).

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:f="http://temp.com/functions">

    <xsl:output method="text"/>
    <xsl:template match="//project/text()">
        <xsl:value-of select="f:getFirstLine(.)"/>
    </xsl:template>

    <xsl:function name="f:getFirstLine">
        <xsl:param name="input"/>
        <xsl:variable name="afterLeadingWS" select="substring-after($input, substring-before($input,substring-before(normalize-space($input), ' ')))"/>
        <xsl:choose>
            <xsl:when test="contains($afterLeadingWS, '&#xA;')">
                 <xsl:value-of select="substring-before($afterLeadingWS, '&#xA;')"/>
            </xsl:when>
            <xsl:otherwise>
                 <xsl:value-of select="$afterLeadingWS"/>
            </xsl:otherwise>
        </xsl:choose>
   </xsl:function>
</xsl:stylesheet>
0 голосов
/ 14 марта 2012

сначала спасибо @Maestro за то, что нашли время и помогли мне, спасибо за вашу помощь. Вот код, который я использовал, чтобы получить первую строку из абзаца текста, который имеет CR:

<xsl:variable name="projNumber" select="ProjectNumber" />
    <xsl:variable name="crlf" select="'&#10;'" />
    <xsl:choose>
      <xsl:when test="contains($projNumber,$crlf)">
        <xsl:value-of select="substring-before($projNumber,$crlf)"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$projNumber"/>
      </xsl:otherwise>
    </xsl:choose>

Это можно записать как функцию, но я не знаю, как это сделать, может быть, кто-то может помочь, но вы идете. Лучший подход, предложенный моим коллегой, состоит в том, чтобы избежать CR и напрямую использовать его в функции подстроки, что в первую очередь позволит избежать всех этих переменных. Еще раз спасибо.

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