Pasujące szablony o różnej konfiguracji w tym samym węźle
Zadałem tutaj całe moje pytanie dotyczące przepełnienia stosu , spróbuję je pokroić:
Muszę utworzyć xml z tego źródła: bardzo krótko:
<?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>...
To jest to, czego potrzebuję:
<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>
Oto pomysł na 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>
Ponieważ zarówno wiersze, jak i nagłówki są zawarte w tagu E1EDL20, widzę potrzebę dwóch szablonów i oba odnoszą się do tego samego tagu w kodzie źródłowym. Jak mówią specyfikacje, używany jest tylko ostatni szablon. (więc zobaczy „nagłówek” i „linie”, ale nie „główne”:
<xsl:template name="main" match="fm:ROW[1]"> ...
<xsl:template name="headers" match="fm:ROW[1]"> ...
<xsl:template name="lines" match="fm:ROW"> ...
Jak to rozwiązać?
Edytować:
@Sebastien: Twoje rozwiązanie działało świetnie w przypadku kodu źródłowego, który dostarczyłem na początku. Doskonała odpowiedź. Zrobiłem jednak błąd w podanym kodzie, przepraszam.
Oto format kodu źródłowego:
<?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>
Wyzwanie polega na tym, że powinienem mieć jeden tag z nagłówkami, ale elementy zamówienia powinny być wymienione jeden pod drugim, na przykład:
<?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>
Dziękuję za wyrozumiałość. Ogromnie doceniam twoją pomoc!
Jestem bardzo zobowiązany, Tom
Odpowiedzi
Oto próbka na początek. W twoim pytaniu brakuje niektórych szczegółów, niektóre przyjąłem pewne zasady.
<?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>
Zobacz, jak działa tutaj: https://xsltfiddle.liberty-development.net/6q1SDka/1