XSLT to text - дочерние узлы с одинаковыми именами - проверка последнего дочернего элемента каждого родителя - PullRequest
0 голосов
/ 29 мая 2018

Мне нужно преобразовать XML в текст, используя XSLT.Вывод, который я получил, содержит все данные в блоке без разделителя или перевода строки, я чувствую, что позиционная часть в XSLT даже не выполняется.

Вопрос : Я хочупроверить позицию последнего потомка каждого родителя и включить новую строку, если это последний потомок (значение столбца) родителя (currentRow) или разделитель, если это не так.

У меня есть XML, который выглядит какниже:

XML-файл:

<?xml version='1.0'?>
<webRowSet xmlns='http://java.sun.com/xml/ns/jdbc'>
<data>
<currentRow>
<columnValue><![CDATA[]]></columnValue>
<columnValue><![CDATA[26068384]]></columnValue>
<columnValue><![CDATA[070-0010055-4842MAR18]]></columnValue>
<columnValue>2018-04-25</columnValue>
<columnValue>170.310</columnValue>
<columnValue><![CDATA[UI-004058]]></columnValue>
</currentRow>
<currentRow><columnValue><![CDATA[]]></columnValue>
<columnValue><![CDATA[26068385]]></columnValue>
<columnValue><![CDATA[070-0010058-5739MAR18]]></columnValue>
<columnValue>2018-04-25</columnValue>
<columnValue>209.900</columnValue>
<columnValue><![CDATA[UI-004057]]></columnValue>
</currentRow>
</data></webRowSet>

XSLT:

<?xml version="1.0"?>
<xsl:stylesheet version ="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="Delimiter"><xsl:text>|</xsl:text></xsl:variable>
<xsl:variable name="NewLine"><xsl:text>&#10;</xsl:text></xsl:variable>
<xsl:template match="/">
<xsl:text>EXPR5_5|VOUCHER_ID|INVOICE_ID|ENTERED_DT|GROSS_AMT|UnifierRecordNo</xsl:text>
<xsl:text>&#10;</xsl:text>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="webRowSet/data">
<xsl:for-each select="currentRow">
<xsl:for-each select="columnValue">
<xsl:value-of select="."/>
<xsl:variable name="Rec_position" select="count(../preceding-sibling::columnValue)+1"/>
<xsl:if test="$Rec_position=6"><xsl:value-of select="$NewLine"/></xsl:if>
<xsl:if test="$Rec_position!=6"><xsl:value-of select="$Delimiter"/></xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Вывод в текстовом формате должен быть таким:

EXPR5_5|VOUCHER_ID|INVOICE_ID|ENTERED_DT|GROSS_AMT|UnifierRecordNo
   |26068384|070-0010055-4842MAR18|2018-04-25|170.310|UI-004058
   |26068385|070-0010058-5739MAR18|2018-04-25|209.900|UI-004057

Ответы [ 2 ]

0 голосов
/ 29 мая 2018

Вы забыли принять во внимание пространство имен.Поэтому добавьте xmlns:j="http://java.sun.com/xml/ns/jdbc" к элементу xsl:stylesheet вашего файла XSLT.Таким образом, вы можете получить доступ ко всем элементам с правильным пространством имен.

Относительно пространства имен измените свой последний шаблон на:

<xsl:template match="j:webRowSet/j:data">
    <xsl:for-each select="j:currentRow">
      <xsl:for-each select="j:columnValue">
        <xsl:value-of select="."/>
        <xsl:variable name="Rec_position" select="position()"/>
        <xsl:if test="$Rec_position=6"><xsl:value-of select="$NewLine"/></xsl:if>
        <xsl:if test="$Rec_position &lt; 6"><xsl:value-of select="$Delimiter"/></xsl:if>
      </xsl:for-each>
    </xsl:for-each>
</xsl:template>

Вывод:

EXPR5_5|VOUCHER_ID|INVOICE_ID|ENTERED_DT|GROSS_AMT|UnifierRecordNo
|26068384|070-0010055-4842MAR18|2018-04-25|170.310|UI-004058
|26068385|070-0010058-5739MAR18|2018-04-25|209.900|UI-004057

Это очень простое решение с минимумом модификаций.

0 голосов
/ 29 мая 2018

У вас есть две проблемы в вашем XSLT.

Во-первых, вы не учли тот факт, что элементы в вашем XML находятся в пространстве имен по умолчанию, как определено xmlns='http://java.sun.com/xml/ns/jdbc в вашем корневом элементе.

Если вы действительно используете только XSLT 1.0, вам нужно связать это пространство имен с префиксом в вашем XSLT, например так ...

xmlns:j="http://java.sun.com/xml/ns/jdbc"

И затем использовать этот префикс перед всемиэлементы в ваших выбранных выражениях.Например ...

 <xsl:template match="j:webRowSet/j:data">

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

 <xsl:variable name="Rec_position" select="count(preceding-sibling::j:columnValue)+1"/>

Хотя функция position() здесь будет делать то же самое.

<xsl:variable name="Rec_position" select="position()"/>

Но вы действительно хотите жестко закодировать число столбцов как6 хоть?Вместо этого попробуйте этот XSLT:

<xsl:stylesheet version ="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:j="http://java.sun.com/xml/ns/jdbc">
<xsl:output method="text" omit-xml-declaration="yes" indent="no"/>

<xsl:strip-space elements="*"/>

<xsl:variable name="Delimiter"><xsl:text>|</xsl:text></xsl:variable>
<xsl:variable name="NewLine"><xsl:text>&#10;</xsl:text></xsl:variable>

<xsl:template match="/">
  <xsl:text>EXPR5_5|VOUCHER_ID|INVOICE_ID|ENTERED_DT|GROSS_AMT|UnifierRecordNo</xsl:text>
  <xsl:value-of select="$NewLine"/>
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="j:webRowSet/j:data">
  <xsl:for-each select="j:currentRow">
    <xsl:for-each select="j:columnValue">
      <xsl:if test="position() != 1"><xsl:value-of select="$Delimiter" /></xsl:if>
      <xsl:value-of select="."/>
    </xsl:for-each>
    <xsl:value-of select="$NewLine"/>
  </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Обратите внимание, если вы можете использовать XSLT 2.0, вы можете написать его так:

<xsl:stylesheet version ="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xpath-default-namespace="http://java.sun.com/xml/ns/jdbc">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>

<xsl:variable name="NewLine"><xsl:text>&#10;</xsl:text></xsl:variable>

<xsl:template match="/">
  <xsl:text>EXPR5_5|VOUCHER_ID|INVOICE_ID|ENTERED_DT|GROSS_AMT|UnifierRecordNo</xsl:text>
  <xsl:value-of select="$NewLine"/>
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="webRowSet/data">
  <xsl:for-each select="currentRow">
    <xsl:value-of select="columnValue" separator="|"/>
    <xsl:value-of select="$NewLine"/>
  </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Обратите внимание на использование xpath-default-namespace, которое делает обработку по умолчаниюПространства имен проще.Кроме того, использование separator на xsl:value-of, которое применяется при выборе нескольких значений.(В XSLT 1.0 xsl:value-of будет отображать только первое значение).

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