Объединение буквенно-цифровых символов в XSLT с тире - PullRequest
0 голосов
/ 07 ноября 2018
<ReferenceDesignators>
<ReferenceDesignator>R1</ReferenceDesignator>
<ReferenceDesignator>R2</ReferenceDesignator>
<ReferenceDesignator>R3</ReferenceDesignator>
<ReferenceDesignator>R4</ReferenceDesignator>
<ReferenceDesignator>R5</ReferenceDesignator>
<ReferenceDesignator>R6</ReferenceDesignator>
<ReferenceDesignator>R7</ReferenceDesignator>
<ReferenceDesignator>R8</ReferenceDesignator>
<ReferenceDesignator>R9</ReferenceDesignator>
<ReferenceDesignator>R10</ReferenceDesignator>
<ReferenceDesignator>R17</ReferenceDesignator>
<ReferenceDesignator>SMD</ReferenceDesignator>
</ReferenceDesignators>

Привет всем, Пожалуйста, посмотрите приведенный выше XML. Я создаю PDF и написал код XSL, как показано ниже.

<xsl:for-each select="ReferenceDesignator">
<xsl:value-of select="."/>
<xsl:if test ="position()!=last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>

Итак, я получаю все значения через запятую. Но я хочу вывод как R1-R10, R17, для поверхностного монтажа.

Как я могу добиться этого, возможно ли это через регулярное выражение. Пожалуйста, помогите.

Спасибо, Манжу

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

В качестве альтернативы приведен шаблон XSLT 3, использующий for-each-group group-adjacent:

  <xsl:template match="ReferenceDesignators">
      <xsl:value-of separator=",">
          <xsl:for-each-group 
            select="ReferenceDesignator" composite="yes"
            group-adjacent="let $p := position(), 
                            $comps := analyze-string(., '(\p{L}+)([0-9]+)'), 
                            $prefix := $comps//*:group[@nr = 1]/data(), $i := $comps//*:group[@nr = 2]/data() 
                            return ($prefix, $i!(xs:integer(.) - $p))">
              <xsl:sequence
              select="string-join((. | current-group()[last()]), '-')"/>
          </xsl:for-each-group>          
      </xsl:value-of>
  </xsl:template>

https://xsltfiddle.liberty -development.net / eiZQaGg / 3

Выражение в атрибуте group-adjacent лучше преобразовать в функцию:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:function name="mf:grouping-key" as="item()+">
      <xsl:param name="value" as="xs:string"/>
      <xsl:param name="pos" as="xs:integer"/>
      <xsl:sequence
        select="let $comps := analyze-string($value, '(\p{L}+)([0-9]+)?'),
                    $prefix := $comps//*:group[@nr = 1]/data(),
                    $suffix := $comps//*:group[@nr = 2]!(xs:integer(.) - $pos)
                return ($prefix, $suffix)"/>
  </xsl:function>

  <xsl:template match="ReferenceDesignators">
      <xsl:value-of separator=",">
          <xsl:for-each-group select="ReferenceDesignator" composite="yes" group-adjacent="mf:grouping-key(., position())">
              <xsl:sequence
              select="string-join((. | current-group()[last()]), '-')"/>
          </xsl:for-each-group>          
      </xsl:value-of>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / eiZQaGg / 4

В XSLT 2 вы можете использовать составной ключ группировки вместо составного:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="#all"
    version="2.0">

  <xsl:function name="mf:grouping-key" as="xs:string">
      <xsl:param name="value" as="xs:string"/>
      <xsl:param name="pos" as="xs:integer"/>
      <xsl:variable name="comps" as="item()*">
          <xsl:variable name="pattern" as="xs:string">(\p{L}+)([0-9]+)?</xsl:variable>
          <xsl:analyze-string select="$value" regex="{$pattern}">
              <xsl:matching-substring>
                  <xsl:sequence select="regex-group(1), regex-group(2)"/>
              </xsl:matching-substring>
          </xsl:analyze-string>
      </xsl:variable>
      <xsl:variable name="prefix" select="$comps[1]"/>
      <xsl:variable name="suffix" select="if ($comps[2] castable as xs:integer) then (xs:integer($comps[2]) - $pos) else ()"/>
      <xsl:sequence
        select="concat($prefix, $suffix)"/>
  </xsl:function>

  <xsl:template match="ReferenceDesignators">
      <xsl:value-of separator=",">
          <xsl:for-each-group select="ReferenceDesignator" group-adjacent="mf:grouping-key(., position())">
              <xsl:sequence
              select="string-join((. | current-group()[last()]), '-')"/>
          </xsl:for-each-group>          
      </xsl:value-of>
  </xsl:template>

</xsl:stylesheet>

http://xsltransform.hikmatu.com/3NzcBsE/1

0 голосов
/ 07 ноября 2018

Один из возможных способов - создать функцию, которую можно использовать для добавления 1 к значению (если в значении присутствует число)

<xsl:function name="my:check">
  <xsl:param name="current" />
  <xsl:variable name="number" select="if (matches($current, '.*\d+')) then xs:int(replace($current, '[A-Z]+', '')) + 1 else ''" />
  <xsl:value-of select="replace($current, '\d', ''), $number" separator="" />
</xsl:function>

Затем вы можете использовать xsl:for-each-group для группировки элементов, начиная с тех, которые не являются последовательными с предыдущим значением

<xsl:for-each-group select="ReferenceDesignator" group-starting-with="ReferenceDesignator[. != my:check(preceding-sibling::ReferenceDesignator[1])]">

Попробуйте это XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" 
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:my="my">

  <xsl:output method="text" />

  <xsl:template match="ReferenceDesignators">
    <xsl:for-each-group select="ReferenceDesignator" group-starting-with="ReferenceDesignator[. != my:check(preceding-sibling::ReferenceDesignator[1])]">
      <xsl:if test="position() > 1">,</xsl:if>
      <xsl:value-of select="current-group()[1], current-group()[position() > 1][last()]" separator="-" />
    </xsl:for-each-group>
  </xsl:template>

  <xsl:function name="my:check">
    <xsl:param name="current" />
    <xsl:variable name="number" select="if (matches($current, '.*\d+')) then xs:int(replace($current, '[A-Z]+', '')) + 1 else ''" />
    <xsl:value-of select="replace($current, '\d', ''), $number" separator="" />
  </xsl:function>
</xsl:stylesheet>

Обратите внимание, что это делает предположение, что каждый ReferenceDesignator состоит из одной или нескольких букв, за которыми следует ноль при большем числе цифр.

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