xsl: преобразовать текст в xml - PullRequest
1 голос
/ 09 марта 2020

Я работаю над преобразованием текста 2 xml, мне нужно преобразовать следующий текст в xml

[header]
CODE VEND = ABCD
TYPE = ORDER
CL CDE = ABDEFGH
CL INV = ABDEFGH
DAT CDE = 03022020
EMAIL = abcd@ .fr
NO CDE = 0000042268
DAT LIV = 03022020
TYP CDE = CDE SPECIALE
NBLIN = 1
CONTRM = ABDEFGH
CL LIV = ABDEFGH
[LINE]
REF VEN = DEFGH
EAN = 123456789
QTE = 1
REF CUST = "AZERTYUOP      "
[end]

мой текущий xsl следующий:

<xsl:stylesheet 
  version="2.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:param name="txt-encoding" as="xs:string" select="'iso-8859-1'"/>
  <xsl:param name="txt-uri" as="xs:string" select="'linktofile'"/>

  <xsl:template match="/" name="text2xml">
    <xsl:variable name="txt" select="unparsed-text($txt-uri, $txt-encoding)"/>
    <xsl:variable name="entries" as="node()*">
      <xsl:analyze-string select="$txt" regex="\r\n?|\n">
        <xsl:non-matching-substring>
          <xsl:analyze-string select="." regex="([^;]*).*=([^;]*)">
            <xsl:matching-substring>
              <entry>
                <nom><xsl:value-of select="normalize-space(regex-group(1))"/>
                </nom>
                <valeur><xsl:value-of select="normalize-space(regex-group(2))"/>
                </valeur>
                <!--text2><xsl:value-of 
                  select="normalize-space(regex-group(3))"/></text2-->
              </entry>
            </xsl:matching-substring>
          </xsl:analyze-string>
        </xsl:non-matching-substring>
      </xsl:analyze-string>
    </xsl:variable>
    <results>
      <xsl:for-each-group select="$entries" group-by="nom">
        <xsl:copy-of
          select="current-group()[1]/nom,current-group()/*[not(self::nom)]"/>
      </xsl:for-each-group>
    </results>
  </xsl:template>

</xsl:stylesheet>

Я могу разделить данные по знаку равенства. Мне нужно следующее:

<CODE_VEND>ABCD</CODE_VEND>
<TYPE>ORDER</TYPE>
<CL_CDE>ABCD</CL_CDE>

+ сгруппировать данные заголовка (между [HEADER] и CL_LIV) на основе <NO_CDE>0000042268</NO_CDE>

Можете ли вы помочь мне в этом,

Спасибо

Обновленное описание Источник

[ENTETE]
CODE VEND = MONH
TYPE = COMMANDE
CL CDE = ABDCDEFG
CL INV = HIJIKL
DAT CDE = 03022020
EMAIL = abcd@.fr
NO CDE = 0000042268
DAT LIV = 03022020
TYP CDE = CDE SPECIALE
NBLIN = 3
CONTRM = ABDCDEFG
CL LIV = ABDCDTERK
[LIGNE]
REF FOU = REFVEN1
GENCOD = EAN11111111
QTE = 1
REF CLI = "XXXXXXXXXXX      "
[LIGNE]
REF FOU = REFVEN2
GENCOD = EAN2222222
QTE = 1
REF CLI = "YYYYYYYYYYYYYYY      "
[LIGNE]
REF FOU = REFVEN3
GENCOD = EAN333333
QTE = 1
REF CLI = "ZZZZZZZZZZZZZZZ      "
[FIN]

Цель

<ORDER>
    <CODE_VEND>MONH</CODE_VEND>
    <TYPE>COMMANDE</TYPE>
    <CL_CDE>ABDCDEFG</CL_CDE>
    <CL_INV>HIJIKL</CL_INV>
    <DAT_CDE>03022020</DAT_CDE>
    <EMAIL>abcd@.fr</EMAIL>
    <NO_CDE>0000042268</NO_CDE>
    <DAT_LIV>03022020</DAT_LIV>
    <TYP_CDE>CDE SPECIALE</TYP_CDE>
    <NBLIN>3</NBLIN>
    <CONTRM>ABDCDEFG</CONTRM>
    <CL_LIV>ABDCDTERK</CL_LIV>
    <LINE>
        <REF_VEN>REFVEN1</REF_VEN>
        <EAN>EAN11111111</EAN>
        <QTE>1</QTE>
        <REF_CLI>XXXXXXXXXXX</REF_CLI>
    </LINE>
    <LINE>
        <REF_VEN>REFVEN2</REF_VEN>
        <EAN>EAN2222222</EAN>
        <QTE>1</QTE>
        <REF_CLI>YYYYYYYYYYYYYYY</REF_CLI>
    </LINE>
    <LINE>
        <REF_VEN>REFVEN3</REF_VEN>
        <EAN>EAN333333</EAN>
        <QTE>1</QTE>
        <REF_CLI>ZZZZZZZZZZZZZZZ</REF_CLI>
    </LINE>
</ORDER>

...

1 Ответ

0 голосов
/ 09 марта 2020

Используя XSLT 3, можно подходить к этому как к задаче группировки: группировать строки из текстовых файлов с помощью group-starting-with, а затем разбивать каждую строку на элемент можно с помощью analyze-string:

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

  <xsl:output indent="yes"/>

  <xsl:mode on-no-match="shallow-skip"/>

  <xsl:param name="txt-encoding" as="xs:string" select="'iso-8859-1'"/>
  <xsl:param name="txt-uri" as="xs:string" select="'linktofile'"/>

  <xsl:template match="/" name="text2xml">

    <xsl:variable name="lines" as="xs:string*" select="unparsed-text-lines($txt-uri, $txt-encoding)"/>

    <xsl:for-each-group select="$lines" group-starting-with=".[. = '[ENTETE]']">
        <ORDER>
            <xsl:for-each-group select="tail(current-group())" group-starting-with=".[. = '[LIGNE]']">
                <xsl:choose>
                    <xsl:when test=". = '[LIGNE]'">
                        <LINE>
                            <xsl:apply-templates select="(current-group() => tail()) ! analyze-string(., '(.+) = (.+)')"/>
                        </LINE>                        
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:apply-templates select="(current-group() => tail()) ! analyze-string(., '(.+) = (.+)')"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </ORDER>
    </xsl:for-each-group>
  </xsl:template>

  <xsl:template match="fn:match">
      <xsl:element name="{replace(normalize-space(fn:group[@nr = 1]), ' ', '_')}">
          <xsl:value-of select="normalize-space(fn:group[@nr = 2])"/>
      </xsl:element>
  </xsl:template>

</xsl:stylesheet>

Онлайн-образец с текстовыми данными, встроенными в https://xsltfiddle.liberty-development.net/bEzknsy.

XSLT 3 доступен с Saxon 9.8 или более поздней версии или Altova XML 2017 R3 и более поздней версии.

Если у вас есть только XSLT 2, вы, конечно, можете использовать первый шаг, который вам необходимо преобразовать в текстовые строки в XML элементы, а затем использовать аналогичный group-starting-with для этих элементов. И, конечно, вместо analyze-string в качестве функции вы можете использовать xsl:analyze-string.

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