同じノードで異なる構成のテンプレートを照合する

Nov 23 2020

私はここでスタックオーバーフローについて質問全体をしました、私はそれを切り刻もうとします:

このソースからxmlを作成する必要があります:非常に簡単に:

    <?xml version="1.0" encoding="UTF-8"?>
    <FMPDSORESULT xmlns="http://www.filemaker.com/fmpdsoresult">
        <ROW>
        <EDI_DC40.TABNAM><DATA>EDI_DC40</DATA></EDI_DC40.TABNAM>
        <E1EDL20.VBELN><DATA>649758</DATA></E1EDL20.VBELN>
        <E1EDL18.QUALF><DATA>ORI</DATA></E1EDL18.QUALF>
        <E1EDT13.1.QUALF><DATA>007<DATA></E1EDT13.1.QUALF>
        <E1EDT13.2.QUALF><DATA>015</DATA></E1EDT13.2.QUALF>
        <E1EDL24.POSNR>000001</E1EDL24.POSNR>
        <E1EDL24.POSNR>2</E1EDL24.POSNR>
                (random number of these)
        <E1EDL41.QUALI>001</E1EDL41.QUALI>
        <E1EDL37.EXIDV><DATA>5650327422</DATA></E1EDL37.EXIDV>
        <E1EDL44.POSNR>000001</E1EDL44.POSNR> <!--(these are the line items, equal to the number of ROW)-->
    </ROW>
    <ROW>...

これは私が必要なものです:

    <DELVRY05>
        <IDOC BEGIN="1">
            <EDI_DC40 SEGMENT="1">
                <TABNAM>EDI-DC40</TABNAM>
            </EDI_DC40>
            <E1EDL20 SEGMENT="1">
                <VBELN>649758</VBELN>
                <E1EDL18 SEGMENT="1"><QUALF>ORI</QUALF></E1EDL18>
                <E1EDT13 SEGMENT="1"><QUALF>007</QUALF></E1EDT13>
                <E1EDT13 SEGMENT="1"><QUALF>015</QUALF></E1EDT13>
                <E1EDL24 SEGMENT="1">
                    <POSNR>000001</POSNR>
                    <E1EDL41 SEGMENT="1">
                        <QUALI>001</QUALI>
                    </E1EDL41>
                </E1EDL24>
                <E1EDL24 SEGMENT="1">
                    <POSNR>2</POSNR>
                    <E1EDL41 SEGMENT="1">
                         <QUALI>001</QUALI>
                    </E1EDL41>
                </E1EDL24>
                <E1EDL24 SEGMENT="1"> <!-- (random number of these, as commented above) -->
                    ...
                </E1EDL24>
            </E1EDL20>
        </IDOC>
    </DELVRY05>

これは私がxslに対して持っていたアイデアです:

    <xsl:template match="/*">
        <DELVRY05>
            <IDOC BEGIN="1">
                <EDI_DC40 SEGMENT="1">
                    <xsl:apply-templates select="headers"/>
                </EDI_DC40>
                <E1EDL20 SEGMENT="1">
                    <xsl:apply-templates select="main"/>
                    <xsl:apply-templates select="fm:ROW"/>
                </E1EDL20>
            </IDOC>
        </DELVRY05>
    </xsl:template>

行とヘッダーの両方がE1EDL20タグに含まれているため、2つのテンプレートが必要であり、どちらもソースコード内の同じタグを参照しています。仕様にあるように、最後のテンプレートのみが使用されています。(したがって、「header」と「lines」は表示されますが、「main」は表示されません:

    <xsl:template name="main" match="fm:ROW[1]"> ...

    <xsl:template name="headers" match="fm:ROW[1]"> ...

    <xsl:template name="lines" match="fm:ROW"> ...

どうすればこれを解決できますか?

編集:

@Sebastien:あなたのソリューションは、私が最初に提供したソースコードに対してうまく機能しました。素晴らしい答え。提供したコードに誤りがありましたが、お詫び申し上げます。

これはソースコードのフォーマットです:

    <?xml version="1.0" encoding="UTF-8"?>
    <FMPDSORESULT xmlns="http://www.filemaker.com/fmpdsoresult">
        <ROW>
            <EDI_DC40.TABNAM><DATA>EDI_DC40</DATA></EDI_DC40.TABNAM>
            <E1EDL20.VBELN><DATA>649758</DATA></E1EDL20.VBELN>
            <E1EDL18.QUALF><DATA>ORI</DATA></E1EDL18.QUALF>
            <E1EDT13.1.QUALF><DATA>007</DATA></E1EDT13.1.QUALF>
            <E1EDT13.2.QUALF><DATA>015</DATA></E1EDT13.2.QUALF>
            <E1EDL24.POSNR>000001</E1EDL24.POSNR>
            <E1EDL41.QUALI>001</E1EDL41.QUALI>
            <E1EDL37.EXIDV><DATA>5650327422</DATA></E1EDL37.EXIDV>
            <E1EDL44.POSNR>000001</E1EDL44.POSNR>
        </ROW>
        <ROW>
            <EDI_DC40.TABNAM><DATA>EDI_DC40</DATA></EDI_DC40.TABNAM>
            <E1EDL20.VBELN><DATA>649758</DATA></E1EDL20.VBELN>
            <E1EDL18.QUALF><DATA>ORI</DATA></E1EDL18.QUALF>
            <E1EDT13.1.QUALF><DATA>007</DATA></E1EDT13.1.QUALF>
            <E1EDT13.2.QUALF><DATA>015</DATA></E1EDT13.2.QUALF>
            <E1EDL24.POSNR>2</E1EDL24.POSNR>
            <E1EDL41.QUALI>002</E1EDL41.QUALI>
            <E1EDL37.EXIDV><DATA>5650327422</DATA></E1EDL37.EXIDV>
            <E1EDL44.POSNR>000001</E1EDL44.POSNR>
        </ROW>
    </FMPDSORESULT>

課題は、ヘッダー付きのタグを1つ持つ必要があることですが、次のように、広告申込情報を相互にリストする必要があります。

    <?xml version="1.0" encoding="utf-16"?>
    <DELVRY05>
      <IDOC BEGIN="1">
        <EDI_DC40 SEGMENT="1">
          <TABNAM>EDI_DC40</TABNAM>
        </EDI_DC40>
        <E1EDL20 SEGMENT="1">
          <VBELN>649758</VBELN>
          <E1EDL18 SEGMENT="1">
            <QUALF>ORI</QUALF>
          </E1EDL18>
          <E1EDL24 SEGMENT="1">
            <POSNR>000001</POSNR>
            <E1EDL41 SEGMENT="1">
              <QUALI>001</QUALI>
            </E1EDL41>
          </E1EDL24>
          <E1EDL24 SEGMENT="1">
            <POSNR>2</POSNR>
            <E1EDL41 SEGMENT="1">
              <QUALI>002</QUALI>
            </E1EDL41>
          </E1EDL24>
        </E1EDL20>
      </IDOC>
    </DELVRY05>

よろしくお願いします。本当にありがとうございました!!

トム、大いに義務づけられた

回答

Sebastien Nov 23 2020 at 16:38

これがあなたが始めるためのサンプルです。あなたの質問には、私がいくつかのルールを想定したいくつかの詳細が欠けています。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:fm="http://www.filemaker.com/fmpdsoresult"
    exclude-result-prefixes="fm"
    version="1.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <DELVRY05>
      <xsl:apply-templates select="fm:FMPDSORESULT/fm:ROW[1]"/>
    </DELVRY05>
  </xsl:template>
  
  <xsl:template match="fm:ROW">
    <IDOC BEGIN="1">
      <EDI_DC40 SEGMENT="1">
        <TABNAM><xsl:value-of select="fm:EDI_DC40.TABNAM/fm:DATA"/></TABNAM>
      </EDI_DC40>
      <E1EDL20 SEGMENT="1">
        <VBELN><xsl:value-of select="fm:E1EDL20.VBELN/fm:DATA"/></VBELN>
        <E1EDL18 SEGMENT="1"><QUALF><xsl:value-of select="fm:E1EDL18.QUALF/fm:DATA"/></QUALF></E1EDL18>
        <!-- Same principle as above for E1EDT13.1, E1EDT1.2, etc. -->
        
        <!-- Use template for elements that are present mutltiple times. -->
        <xsl:apply-templates select="../fm:ROW/fm:E1EDL24.POSNR"/>
      </E1EDL20>
    </IDOC>
  </xsl:template>
  
  <xsl:template match="fm:E1EDL24.POSNR">
    <E1EDL24 SEGMENT="1">
      <POSNR><xsl:value-of select="."/></POSNR>
      <E1EDL41 SEGMENT="1">
        <QUALI><xsl:value-of select="../fm:E1EDL41.QUALI"/></QUALI>
      </E1EDL41>
    </E1EDL24>
  </xsl:template>
  
</xsl:stylesheet>

ここで動作するのを見てください: https://xsltfiddle.liberty-development.net/6q1SDka/1