XSLT + синтаксический анализ строк с несколькими критериями - PullRequest
0 голосов
/ 24 января 2012

Я пытаюсь проанализировать следующую строку сообщения:

"Row 1> testdata1 |Row 5> testdata2 |Row 7> testdata3"

в формате таблицы HTML:

<tr>
  <td>Row 1</td><td>testdata1</td>
  <td>Row 5</td><td>testdata2</td>
  <td>Row 7</td><td>testdata3</td>
</td>

Вот моя текущая попытка:

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

<xsl:template match="col1" >
  <xsl:call-template name="parseStr" >
    <xsl:with-param name="txt" select="text()" />
  </xsl:call-template>
</xsl:template>

<xsl:template name="parseStr">
  <xsl:param name="txt" select="''" />
    <tr><xsl:choose>
      <xsl:when test="contains($txt, '>')" >
        <td><xsl:value-of select="substring-before($txt, '>')" /></td><td><xsl:value-of select="substring-after($txt, '>')" /></td>
      </xsl:when>

      <xsl:otherwise>
         <td><xsl:value-of select="$txt" /></td>
      </xsl:otherwise>
    </xsl:choose></tr>

    <xsl:variable name="leftStr" select="substring-after($txt, '|')" />
    <xsl:if test="string-length($leftStr)>1" >
      <xsl:call-template name="parseStr" >
        <xsl:with-param name="txt" select="$leftStr" />
      </xsl:call-template>
    </xsl:if>

</xsl:template>

Этот XSLT обеспечивает правильную структуру таблицы.У меня возникают трудности с разделением строк тестовых данных после начального> перерыва.

Вывод:

<tr>
  <td>Row 1</td><td>testdata1 |Row 5> testdata2 |Row 7> testdata3</td>
  <td>Row 5</td><td>testdata2 |Row 7> testdata3</td>
  <td>Row 7</td><td>testdata 3</td>
</tr>

ОБНОВЛЕНИЕ Я выяснил, как захватить текст между строками.Я добавил следующее:

<td><xsl:value-of select="substring-before($txt, '>')" /></td><td><xsl:value-of select="substring-after(substring-before($txt, '|'), '>')" /></td>

Однако мне не хватает последнего проанализированного сообщения "testdata3".

Кроме того, вот исходный XML:

<Rowsets>
  <Rowset>
    <Row>
      <col1>Row 1> testdata1 |Row 5> testdata2 |Row 7> testdata3</col1>
    </Row>
  </Rowset>
</Rowsets>

ОБНОВЛЕНИЕ 2:

успех!Я нашел решение для этого;однако, может быть более простой / чистый способ ... вот мое решение, если вы заинтересованы: -)

 <xsl:template name="parseStr">
   <xsl:param name="txt" select="''" />
     <tr><xsl:choose>
       <xsl:when test="contains($txt, '|')" >
         <td><xsl:value-of select="substring-before($txt, '>')" /></td><td><xsl:value-of select="substring-after(substring-before($txt, '|'), '>')"/></td>
       </xsl:when>
       <xsl:otherwise>
         <td><xsl:value-of select="substring-before($txt, '>')" /></td><td><xsl:value-of select="substring-after($txt, '>')" /></td>
       </xsl:otherwise>
     </xsl:choose></tr>

   <xsl:variable name="leftStr" select="substring-after($txt, '|')" />
   <xsl:if test="string-length($leftStr)>1" >
     <xsl:call-template name="parseStr" >
       <xsl:with-param name="txt" select="$leftStr" />
     </xsl:call-template>
   </xsl:if>

</xsl:template>

Ответы [ 2 ]

4 голосов
/ 25 января 2012

I. Это XSLT 1.0 преобразование :

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

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

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

  <xsl:if test="string($pStr)">
   <xsl:variable name="vText" select="concat($pStr, ' |')"/>
   <xsl:variable name="vPair" select=
    "substring-before($vText, ' |')"/>
   <td>
    <xsl:value-of select="substring-before($vPair, '> ')"/>
   </td>
   <td>
    <xsl:value-of select="substring-after($vPair, '> ')"/>
   </td>

   <xsl:call-template name="makeTDs">
     <xsl:with-param name="pStr" select=
      "substring-after($pStr, ' |')"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

при применении к этому документу XML :

<t>Row 1> testdata1 |Row 5> testdata2 |Row 7> testdata3</t>

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

<tr>
   <td>Row 1</td>
   <td>testdata1</td>
   <td>Row 5</td>
   <td>testdata2</td>
   <td>Row 7</td>
   <td>testdata3</td>
</tr>

II. Решение XSLT 2.0 :

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

 <xsl:template match="/*">
  <tr>
    <xsl:for-each select="tokenize(., ' \|')">
     <xsl:for-each select="tokenize(., '> ')">
       <td><xsl:sequence select="."/></td>
     </xsl:for-each>
    </xsl:for-each>
  </tr>
 </xsl:template>
</xsl:stylesheet>

это преобразование при применении к тому же XML-документу (см. Выше) дает тот же правильный результат:

<tr>
   <td>Row 1</td>
   <td>testdata1</td>
   <td>Row 5</td>
   <td>testdata2</td>
   <td>Row 7</td>
   <td>testdata3</td>
</tr>
0 голосов
/ 24 января 2012

Я немного пытаюсь понять ваш входной XML - не запутался ли он редактором.Это, конечно, не выглядит правильно сформированным XML, и я не вижу элементов <Row> или <Col>.

Однако эта строка выглядит неправильно:

<xsl:param name="txt" select="''" />

Я думаю, что это должно просто читать

<xsl:param name="txt">
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...