Ahoj...
mám foreach cyklus a v něm vytvářím XML strukturu. První kolo cyklu vytvoří část struktury a v dalším kole bych potřeboval pomocí xpath axes se na tu strukturu dostat. Lze to vůbec?
Potřeboval bych získat hodnotu elementu ze struktury, kterou vytvořilo předchozí kolo cyklu.
<xsl:for-each select="/bla/bla/bla/neco">
<xsl:variable name="Round" select="position()"></xsl:variable>
<Pack>
<Parent>Pallet</Parent>
<xsl:choose>
<xsl:when test="$Round='1'">
<Number><xsl:value-of select="position()"></xsl:value-of></Number>
</xsl:when>
<xsl:otherwise>
<Number><xsl:value-of select="./ancestor::Pack/Number +1"></xsl:value-of></Number>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
Zkus zapomenout na existenci xsl:for-each a udělej to pořádně. Uvidíš, že to bude o dost jednodušší.
Dodej sem ukázku XML a požadovaný výsledek. Testovací data se mi vymejšlet nechce.
Citace od: Kit kdy 17. 07. 2021, 13:36:38
Zkus zapomenout na existenci xsl:for-each a udělej to pořádně. Uvidíš, že to bude o dost jednodušší.
Dodej sem ukázku XML a požadovaný výsledek. Testovací data se mi vymejšlet nechce.
XML struktura vzniká právě v tom cyklu foreach.
Citace od: ZAJDAN kdy 17. 07. 2021, 13:40:55
Citace od: Kit kdy 17. 07. 2021, 13:36:38
Zkus zapomenout na existenci xsl:for-each a udělej to pořádně. Uvidíš, že to bude o dost jednodušší.
Dodej sem ukázku XML a požadovaný výsledek. Testovací data se mi vymejšlet nechce.
XML struktura vzniká právě v tom cyklu foreach.
Měl jsem na mysli vstupní XML. Mám si ho snad vycucat z prstu?
Citace od: Kit kdy 17. 07. 2021, 13:44:56
Měl jsem na mysli vstupní XML. Mám si ho snad vycucat z prstu?
Vstupní struktura je zde k ničemu, protože na ni se jen odkazuju cyklusem. Nebudu sem dávat kompletní vstup(je obrovskej), ale logika je takováto.
Vstupní payload:
<ResultsSet>
<ResultSet>
<Row><Parent>11</Parent></Row>
<Row><Parent>10</Parent></Row>
<Row><Parent>6</Parent></Row>
</ResultSet>
<ResultSet>
<Row>
<Child>aaa</Child>
<Parent>11</Parent>
</Row>
<Row>
<Child>bbb</Child>
<Parent>11</Parent>
</Row>
<Row>
<Child>ccc</Child>
<Parent>10</Parent>
</Row>
<Row>
<Child>ddd</Child>
<Parent>10</Parent>
</Row>
<Row>
<Child>zzz</Child>
<Parent>6</Parent>
</Row>
</ResultSet>
</ResultsSet>
V následujícím payloadu:
<xsl:for-each select="/ResultsSet/ResultSet[1]/Row">
<xsl:variable name="Round" select="position()"></xsl:variable>
<Pack>
<Parent>Pallet</Parent>
<ID><xsl:value-of select="Parent"/></Parent>
<xsl:choose>
<xsl:when test="$Round='1'">
<Number><xsl:value-of select="position()"></xsl:value-of></Number>
</xsl:when>
<xsl:otherwise>
<Number><xsl:value-of select="./ancestor::Pack/Number +1"></xsl:value-of></Number>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>S osama potřebuji pracovat až na nově vznikající xml struktuře uvnitř cyklu. Hodnota v elementu <Number> se bude měnit ještě na základě jiných podmínek, ale do toho nemá smysl zabředávat. Otazka zní, zda se pomocí xpath axes dá ukazovat na strukturu, která je vytvořena v předchozím kole cyklu.
Citace od: ZAJDAN kdy 17. 07. 2021, 14:10:23
Citace od: Kit kdy 17. 07. 2021, 13:44:56
Měl jsem na mysli vstupní XML. Mám si ho snad vycucat z prstu?
Vstupní struktura je zde k ničemu, protože na ni se jen odkazuju cyklusem. Nebudu sem dávat kompletní vstup(je obrovskej), ale logika je takováto.
Vstupní payload:
<ResultsSet>
<ResultSet>
<Row><Parent>11</Parent></Row>
<Row><Parent>10</Parent></Row>
<Row><Parent>6</Parent></Row>
</ResultSet>
<ResultSet>
<Row>
<Child>aaa</Child>
<Parent>11</Parent>
</Row>
<Row>
<Child>bbb</Child>
<Parent>11</Parent>
</Row>
<Row>
<Child>ccc</Child>
<Parent>10</Parent>
</Row>
<Row>
<Child>ddd</Child>
<Parent>10</Parent>
</Row>
<Row>
<Child>zzz</Child>
<Parent>6</Parent>
</Row>
</ResultSet>
</ResultsSet>
V následujícím payloadu:
<xsl:for-each select="/ResultsSet/ResultSet[1]/Row">
<xsl:variable name="Round" select="position()"></xsl:variable>
<Pack>
<Parent>Pallet</Parent>
<ID><xsl:value-of select="Parent"/></Parent>
<xsl:choose>
<xsl:when test="$Round='1'">
<Number><xsl:value-of select="position()"></xsl:value-of></Number>
</xsl:when>
<xsl:otherwise>
<Number><xsl:value-of select="./ancestor::Pack/Number +1"></xsl:value-of></Number>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
S osama potřebuji pracovat až na nově vznikající xml struktuře uvnitř cyklu. Hodnota v elementu <Number> se bude měnit ještě na základě jiných podmínek, ale do toho nemá smysl zabředávat. Otazka zní, zda se pomocí xpath axes dá ukazovat na strukturu, která je vytvořena v předchozím kole cyklu.
Předpokládejme, že chceš takovýto výstup:
<Workbook>
<Pack>
<ID>11</ID>
<Items>
<Child>aaa</Child>
<Child>bbb</Child>
</Items>
</Pack>
<Pack>
<ID>10</ID>
<Items>
<Child>ccc</Child>
<Child>ddd</Child>
</Items>
</Pack>
<Pack>
<ID>6</ID>
<Items>
<Child>zzz</Child>
</Items>
</Pack>
</Workbook>Takhle by to nešlo?
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:template match="/">
<Workbook>
<xsl:call-template name="Pack" />
</Workbook>
</xsl:template>
<xsl:template name="Pack">
<xsl:for-each select="/ResultsSet/ResultSet[1]/Row">
<xsl:variable name="Parent" select="Parent"/>
<Pack>
<ID><xsl:value-of select="Parent"/></ID>
<Items>
<xsl:for-each select="/ResultsSet/ResultSet[2]/Row[Parent = $Parent]">
<Child><xsl:value-of select="Child"/></Child>
</xsl:for-each>
</Items>
</Pack>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Mám za to, že ve foreach v každé iteraci pracuje vždy s původním zdrojem. Tudíž tak jak si to představuješ to nejde. (Ani to není dobrý nápad, mění se ti data pod rukama.)
Takže mě napadají dva způsoby:
1/ buď nepracovat s lokálním nodem, ale jít o úroveň víš, a zpracovat si v ciklu najednou všechno co potřebuješ (viz má ukázka)
2/ nebo nejdřív zpracovat část v celém ciklu, a pak nad výsledkem projet nové kolo s další logikou - volat šablonu nad výsledkem jiné šablony (to žel neumím).
Citace od: ZAJDAN kdy 17. 07. 2021, 14:10:23
Otazka zní, zda se pomocí xpath axes dá ukazovat na strukturu, která je vytvořena v předchozím kole cyklu.
Nijak rozumně ne, protože to popírá celý princip, na kterém je XSLT založeno. XSLT není imperativní ale deklarativní, např. jako SQL. V předchozím cyklu se nemůže dít nic magického, co by nešlo získat z původních dat.
V tom vašem příkladu je
xsl:for-each úplně zbytečné, použijte normální
xsl:apply-templates. A tam, kde se pokoušíte odkazovat na předchozí pole cyklu, se normálně odkažte na původní data, ze kterých jste to chtěl v tom cyklu počítat.
Konkrétně ten váš pseudopříklad, kde jste se chtěl odkazovat na předchozí kolo cyklu, se dá přepsat na triviální:
<xsl:template match="/ResultsSet/ResultSet[1]/Row">
<Pack>
<Parent>Pallet</Parent>
<ID><xsl:value-of select="Parent"/></Parent>
<Number><xsl:value-of select="position()" /></Number>
</Pack>
</xsl:for-each>
Citace od: Filip Jirsák kdy 17. 07. 2021, 18:35:01
Konkrétně ten váš pseudopříklad, kde jste se chtěl odkazovat na předchozí kolo cyklu, se dá přepsat na triviální:
<xsl:template match="/ResultsSet/ResultSet[1]/Row">
<Pack>
<Parent>Pallet</Parent>
<ID><xsl:value-of select="Parent"/></Parent>
<Number><xsl:value-of select="position()" /></Number>
</Pack>
</xsl:for-each>
Až na tu chybu na posledním řádku a chybné párování ID a Parent to vypadá dobře.
1) Omlouvám se za nepřesný popis případu, níže to vyjasním lépe.
2) To co chci, dokážu, ale tak, že zpracuji cyklem a XML výstup v dalším payloadu ztransformuju.
3) To stejné bych ale chtěl docílit v rámci jednoho payloadu, pravděpodobně pomocí template jak tady zmiňujete.
V ResultSet[1] mám seznam palet. V ResultSet[2] mám seznam krabic a na jaké paletě leží <Parent>.
Celý problém tkví v tom, že v hlavním xsl:foreach cyklu je ještě vnitřní cyklus a v obouch používám position().
Ve vnitřním cyklu jen přičítám +1 aby sekvenční číslo jednotlivých <Package> iterovalo správně.
Takže vznikne první element Package typu paleta a následujou Package typu box co jsou na ní naloženy. Pak další Package typu paleta a za ním Package typu box co jsou na ní.
Havní problém je v tom, že se počítá pomocí position() v obou cyklech a tím nikdy nevznikne postupné číslování.
Další, co pak budu řešit, je přiřadit všem Package typu Box sekvenční číslo jejich palety/rodiče.
<ResultsSet>
<ResultSet>
<Row><Parent>11</Parent></Row>
<Row><Parent>10</Parent></Row>
<Row><Parent>6</Parent></Row>
</ResultSet>
<ResultSet>
<Row>
<Child>aaa</Child>
<Parent>11</Parent>
</Row>
<Row>
<Child>bbb</Child>
<Parent>11</Parent>
</Row>
<Row>
<Child>ccc</Child>
<Parent>10</Parent>
</Row>
<Row>
<Child>ddd</Child>
<Parent>10</Parent>
</Row>
<Row>
<Child>zzz</Child>
<Parent>6</Parent>
</Row>
</ResultSet>
</ResultsSet>
<xsl:for-each select="/ResultsSet/ResultSet[1]/Row">
<xsl:variable name="Parent" select="/ResultsSet/ResultSet[1]/Row/Parent"></xsl:variable>
<Pack>
<Type>Pallet<Type>
<ID><xsl:value-of select="Parent"/></ID>
<Sequence><xsl:value-of select="position()"></Sequence>
</Pack>
<xsl:for-each select="/ResultsSet/ResultSet[2]/Row[Parent='$Parent']">
<Pack>
<Type>Box<Type>
<ID><xsl:value-of select="Child"></ID>
<Sequence><xsl:value-of select="position() +1"></Sequence>
<Parent>sekvenční číslo rodičovské palety</Parent>
</Pack>
</xsl:for-each>
Co takhle zkusit použít<xsl:number>?
Citace od: ZAJDAN kdy 17. 07. 2021, 21:24:15
1) Omlouvám se za nepřesný popis případu, níže to vyjasním lépe.
2) To co chci, dokážu, ale tak, že zpracuji cyklem a XML výstup v dalším payloadu ztransformuju.
3) To stejné bych ale chtěl docílit v rámci jednoho payloadu, pravděpodobně pomocí template jak tady zmiňujete.
V ResultSet[1] mám seznam palet. V ResultSet[2] mám seznam krabic a na jaké paletě leží <Parent>.
Celý problém tkví v tom, že v hlavním xsl:foreach cyklu je ještě vnitřní cyklus a v obouch používám position().
Ve vnitřním cyklu jen přičítám +1 aby sekvenční číslo jednotlivých <Package> iterovalo správně.
Takže vznikne první element Package typu paleta a následujou Package typu box co jsou na ní naloženy. Pak další Package typu paleta a za ním Package typu box co jsou na ní.
Havní problém je v tom, že se počítá pomocí position() v obou cyklech a tím nikdy nevznikne postupné číslování.
Další, co pak budu řešit, je přiřadit všem Package typu Box sekvenční číslo jejich palety/rodiče.
<ResultsSet>
<ResultSet>
<Row><Parent>11</Parent></Row>
<Row><Parent>10</Parent></Row>
<Row><Parent>6</Parent></Row>
</ResultSet>
<ResultSet>
<Row>
<Child>aaa</Child>
<Parent>11</Parent>
</Row>
<Row>
<Child>bbb</Child>
<Parent>11</Parent>
</Row>
<Row>
<Child>ccc</Child>
<Parent>10</Parent>
</Row>
<Row>
<Child>ddd</Child>
<Parent>10</Parent>
</Row>
<Row>
<Child>zzz</Child>
<Parent>6</Parent>
</Row>
</ResultSet>
</ResultsSet>
<xsl:for-each select="/ResultsSet/ResultSet[1]/Row">
<xsl:variable name="Parent" select="/ResultsSet/ResultSet[1]/Row/Parent"></xsl:variable>
<Pack>
<Type>Pallet<Type>
<ID><xsl:value-of select="Parent"/></ID>
<Sequence><xsl:value-of select="position()"></Sequence>
</Pack>
<xsl:for-each select="/ResultsSet/ResultSet[2]/Row[Parent='$Parent']">
<Pack>
<Type>Box<Type>
<ID><xsl:value-of select="Child"></ID>
<Sequence><xsl:value-of select="position() +1"></Sequence>
<Parent>sekvenční číslo rodičovské palety</Parent>
</Pack>
</xsl:for-each>
Takže výsledek má vypadat takto?
<Workbook>
<Pack>
<Type>Pallet<Type>
<ID>11</ID>
<Sequence>1</Sequence>
</Pack>
<Pack>
<Type>Pallet<Type>
<ID>10</ID>
<Sequence>2</Sequence>
</Pack>
<Pack>
<Type>Pallet<Type>
<ID>6</ID>
<Sequence>3</Sequence>
</Pack>
<Pack>
<Type>Box<Type>
<ID>aaa</ID>
<Sequence>1</Sequence>
<Parent>1</Parent>
</Pack>
<Pack>
<Type>Box<Type>
<ID>bbb</ID>
<Sequence>2</Sequence>
<Parent>1</Parent>
</Pack>
<Pack>
<Type>Box<Type>
<ID>ccc</ID>
<Sequence>3</Sequence>
<Parent>2</Parent>
</Pack>
<Pack>
<Type>Box<Type>
<ID>ddd</ID>
<Sequence>4</Sequence>
<Parent>2</Parent>
</Pack>
<Pack>
<Type>Box<Type>
<ID>zzz</ID>
<Sequence>5</Sequence>
<Parent>3</Parent>
</Pack>
</Workbook>
nebo takhle?
<Workbook>
<Pack>
<Type>Pallet<Type>
<ID>11</ID>
<Sequence>1</Sequence>
</Pack>
<Pack>
<Type>Pallet<Type>
<ID>10</ID>
<Sequence>2</Sequence>
</Pack>
<Pack>
<Type>Pallet<Type>
<ID>6</ID>
<Sequence>3</Sequence>
</Pack>
<Pack>
<Type>Box<Type>
<ID>aaa</ID>
<Sequence>1</Sequence>
<Parent>1</Parent>
</Pack>
<Pack>
<Type>Box<Type>
<ID>bbb</ID>
<Sequence>2</Sequence>
<Parent>1</Parent>
</Pack>
<Pack>
<Type>Box<Type>
<ID>ccc</ID>
<Sequence>1</Sequence>
<Parent>2</Parent>
</Pack>
<Pack>
<Type>Box<Type>
<ID>ddd</ID>
<Sequence>2</Sequence>
<Parent>2</Parent>
</Pack>
<Pack>
<Type>Box<Type>
<ID>zzz</ID>
<Sequence>1</Sequence>
<Parent>3</Parent>
</Pack>
</Workbook>
Citace od: ZAJDAN kdy 17. 07. 2021, 21:24:15
...
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:template match="/">
<Workbook>
<xsl:call-template name="Pack" />
</Workbook>
</xsl:template>
<xsl:template name="Pack">
<xsl:for-each select="/ResultsSet/ResultSet[1]/Row">
<xsl:variable name="ParentId" select="Parent"/>
<xsl:variable name="ParentIndex" select="position()"/>
<Pack>
<Type>Pallet</Type>
<ID><xsl:value-of select="Parent"/></ID>
<Sequence><xsl:value-of select="position()" /></Sequence>
</Pack>
<xsl:for-each select="/ResultsSet/ResultSet[2]/Row[Parent = $ParentId]">
<Pack>
<Type>Box</Type>
<Child><xsl:value-of select="Child"/></Child>
<Sequence><xsl:value-of select="position()" /></Sequence>
<Parent><xsl:value-of select="$ParentIndex" /></Parent>
</Pack>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Výsledek by měl být Paleta, boxy na ní, Paleta, boxy na ní.
<Workbook>
<Pack>
<Type>Pallet<Type>
<ID>11</ID>
<Sequence>1</Sequence>
</Pack>
<Pack>
<Type>Box<Type>
<ID>aaa</ID>
<Sequence>2</Sequence>
<Parent>1</Parent>
</Pack>
<Type>Box<Type>
<ID>bbb</ID>
<Sequence>3</Sequence>
<Parent>1</Parent>
</Pack>
<Pack>
<Type>Pallet<Type>
<ID>10</ID>
<Sequence>4</Sequence>
</Pack>
<Pack>
<Type>Box<Type>
<ID>ccc</ID>
<Sequence>5</Sequence>
<Parent>4</Parent>
</Pack>
<Type>Box<Type>
<ID>ddd</ID>
<Sequence>6</Sequence>
<Parent>4</Parent>
</Pack>
<Type>Pallet<Type>
<ID>6</ID>
<Sequence>7</Sequence>
</Pack>
<Pack>
<Type>Box<Type>
<ID>zzz</ID>
<Sequence>8</Sequence>
<Parent>7</Parent>
</Pack>
</Workbook>
Citace od: ZAJDAN kdy 17. 07. 2021, 22:54:15
Výsledek by měl být Paleta, boxy na ní, Paleta, boxy na ní.
<Workbook>
<Pack>
<Type>Pallet<Type>
<ID>11</ID>
<Sequence>1</Sequence>
</Pack>
<Pack>
<Type>Box<Type>
<ID>aaa</ID>
<Sequence>2</Sequence>
<Parent>1</Parent>
</Pack>
<Type>Box<Type>
<ID>bbb</ID>
<Sequence>3</Sequence>
<Parent>1</Parent>
</Pack>
<Pack>
<Type>Pallet<Type>
<ID>10</ID>
<Sequence>4</Sequence>
</Pack>
<Pack>
<Type>Box<Type>
<ID>ccc</ID>
<Sequence>5</Sequence>
<Parent>4</Parent>
</Pack>
<Type>Box<Type>
<ID>ddd</ID>
<Sequence>6</Sequence>
<Parent>4</Parent>
</Pack>
<Type>Pallet<Type>
<ID>6</ID>
<Sequence>7</Sequence>
</Pack>
<Pack>
<Type>Box<Type>
<ID>zzz</ID>
<Sequence>8</Sequence>
<Parent>7</Parent>
</Pack>
</Workbook>
Takhle?:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:template match="/">
<Workbook>
<xsl:call-template name="Pack" />
</Workbook>
</xsl:template>
<xsl:template name="Pack">
<xsl:for-each select="/ResultsSet/ResultSet[1]/Row">
<xsl:variable name="ParentIndex" select="position()"/>
<xsl:variable name="ParentId" select="Parent"/>
<xsl:for-each select="/ResultsSet/ResultSet[2]/Row[Parent = $ParentId]">
<xsl:if test="position() = 1">
<xsl:variable name="ParentSequence" select="$ParentIndex + count(preceding-sibling::Row)"/>
<Pack>
<Type>Pallet</Type>
<ID><xsl:value-of select="$ParentId"/></ID>
<Sequence><xsl:value-of select="$ParentSequence" /></Sequence>
</Pack>
<xsl:for-each select="/ResultsSet/ResultSet[2]/Row[Parent = $ParentId]">
<Pack>
<Type>Box</Type>
<Child><xsl:value-of select="Child"/></Child>
<Parent><xsl:value-of select="$ParentSequence" /></Parent>
<Sequence><xsl:value-of select="$ParentIndex + 1 + count(preceding-sibling::Row)" /></Sequence>
</Pack>
</xsl:for-each>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Citace od: BoneFlute kdy 18. 07. 2021, 00:15:59
....
Díky zkusil jsem, ale Sekvence je počítána špatně.
Cílem je, aby sekvence šla plynule za sebou, bez ohledu na to, zda je to paleta nebo box.
A u boxů pak dosazovat do <Parent> sekvenci jejich palety.
Citace od: ZAJDAN kdy 18. 07. 2021, 01:06:48
Citace od: BoneFlute kdy 18. 07. 2021, 00:15:59
....
Díky zkusil jsem, ale Sekvence je počítána špatně.
Cílem je, aby sekvence šla plynule za sebou, bez ohledu na to, zda je to paleta nebo box.
A u boxů pak dosazovat do <Parent> sekvenci jejich palety.
Toto je výsledek:
<?xml version="1.0" encoding="utf-8"?>
<Workbook>
<Pack>
<Type>Pallet</Type>
<ID>11</ID>
<Sequence>1</Sequence>
</Pack>
<Pack>
<Type>Box</Type>
<Child>aaa</Child>
<Parent>1</Parent>
<Sequence>2</Sequence>
</Pack>
<Pack>
<Type>Box</Type>
<Child>bbb</Child>
<Parent>1</Parent>
<Sequence>3</Sequence>
</Pack>
<Pack>
<Type>Pallet</Type>
<ID>10</ID>
<Sequence>4</Sequence>
</Pack>
<Pack>
<Type>Box</Type>
<Child>ccc</Child>
<Parent>4</Parent>
<Sequence>5</Sequence>
</Pack>
<Pack>
<Type>Box</Type>
<Child>ddd</Child>
<Parent>4</Parent>
<Sequence>6</Sequence>
</Pack>
<Pack>
<Type>Pallet</Type>
<ID>6</ID>
<Sequence>7</Sequence>
</Pack>
<Pack>
<Type>Box</Type>
<Child>zzz</Child>
<Parent>7</Parent>
<Sequence>8</Sequence>
</Pack>
</Workbook>Tobě to nedělá? Nebo to je špatnej výsledek?
Používám Xalan, ale mělo by to být natolik standardní, že by na tom nemělo záležet.
Palety iterují jen na sobě, boxy jen v jednom kole.
Počítá mi to takto:
<Pack>
<Type>Pallet</Type>
<ID>11</ID>
<Sequence>1</Sequence>
</Pack>
<Pack>
<Type>Box</Type>
<Child>aaa</Child>
<Parent>1</Parent>
<Sequence>2</Sequence>
</Pack>
<Pack>
<Type>Box</Type>
<Child>bbb</Child>
<Parent>1</Parent>
<Sequence>2</Sequence>
</Pack>
<Pack>
<Type>Pallet</Type>
<ID>10</ID>
<Sequence>2</Sequence>
</Pack>
<Pack>
<Type>Box</Type>
<Child>ccc</Child>
<Parent>2</Parent>
<Sequence>3</Sequence>
</Pack>
<Pack>
<Type>Box</Type>
<Child>ddd</Child>
<Parent>2</Parent>
<Sequence>3</Sequence>
</Pack>
<Pack>
<Type>Pallet</Type>
<ID>6</ID>
<Sequence>3</Sequence>
</Pack>
<Pack>
<Type>Box</Type>
<Child>zzz</Child>
<Parent>3</Parent>
<Sequence>4</Sequence>
</Pack>
Citace od: ZAJDAN kdy 17. 07. 2021, 21:24:15
Ve vnitřním cyklu jen přičítám +1 aby sekvenční číslo jednotlivých <Package> iterovalo správně.
To je přímo vzorový příklad, kdy nemůžete použít
for-each.
K očíslování vstupních elementů slouží
<xsl:number />. Takže tam, kde potřebujete získat pořadové číslo, použijte
<xsl:number count="Pack" select="XXX"/> kde za
XXX dosadíte selektor pro uzel, jehož pořadí potřebujete získat – v případě palety to tedy bude aktuální uzel, v případě boxu to bude uzel získaný přes
Parent.
Citace od: Filip Jirsák kdy 18. 07. 2021, 11:04:02
K očíslování vstupních elementů slouží <xsl:number />. Takže tam, kde potřebujete získat pořadové číslo, použijte <xsl:number count="Pack" select="XXX"/> kde za XXX dosadíte selektor pro uzel, jehož pořadí potřebujete získat – v případě palety to tedy bude aktuální uzel, v případě boxu to bude uzel získaný přes Parent.
Včera tady někdo xsl:number zmiňoval, díval jsem se, ale atribut 'select' se tam nezmiňuje:
https://www.w3schools.com/XML/ref_xsl_el_number.asp
Citace od: ZAJDAN kdy 18. 07. 2021, 11:23:49
Citace od: Filip Jirsák kdy 18. 07. 2021, 11:04:02
K očíslování vstupních elementů slouží <xsl:number />. Takže tam, kde potřebujete získat pořadové číslo, použijte <xsl:number count="Pack" select="XXX"/> kde za XXX dosadíte selektor pro uzel, jehož pořadí potřebujete získat – v případě palety to tedy bude aktuální uzel, v případě boxu to bude uzel získaný přes Parent.
Včera tady někdo xsl:number zmiňoval, díval jsem se, ale atribut 'select' se tam nezmiňuje:
https://www.w3schools.com/XML/ref_xsl_el_number.asp
To jsem byl já. Tady je malá sbírka použití:
https://www.oreilly.com/library/view/xslt-2nd-edition/9780596527211/ch04s03.html (https://www.oreilly.com/library/view/xslt-2nd-edition/9780596527211/ch04s03.html)
Atribut select tam skutečně není, ale jsou tam atributy from a value, které plní tuto funkci.
Citace od: Kit kdy 18. 07. 2021, 11:55:43
To jsem byl já. Tady je malá sbírka použití:
https://www.oreilly.com/library/view/xslt-2nd-edition/9780596527211/ch04s03.html (https://www.oreilly.com/library/view/xslt-2nd-edition/9780596527211/ch04s03.html)
Atribut select tam skutečně není, ale jsou tam atributy from a value, které plní tuto funkci.
Každopádně pokud jsem to dobře pochopil, tak uvnitř for-each nemůžu odkazovat na XML elementy, které v něm vznikají, ale musím se odkazovat na vstupní XML strukturu kterou má cyklus v selektu. V mém případě bych tedy v xsl:number ukazoval na ResultSet/Row, etc a to mi asi nepomůže.
Citace od: ZAJDAN kdy 18. 07. 2021, 11:23:49
Včera tady někdo xsl:number zmiňoval, díval jsem se, ale atribut 'select' se tam nezmiňuje:
https://www.w3schools.com/XML/ref_xsl_el_number.asp
Když píšu o XSLT, myslím tím aktuální specifikaci XSLT 3.0. Clickbaitové weby jako w3schools nemá smysl zmiňovat, stejně jako 14 let starou knihu. Nejlepší je použít dokumentaci Saxonu – xsl:number (https://www.saxonica.com/documentation10/index.html#!xsl-elements/number). Asi nepoužíváte žádný proprietární XSLT procesor, takže stejně používáte Saxon, ve světě OSS není jiná alternativa, která by se Saxonu alespoň blížila.
Citace od: ZAJDAN kdy 18. 07. 2021, 12:05:01
Každopádně pokud jsem to dobře pochopil, tak uvnitř for-each nemůžu odkazovat na XML elementy, které v něm vznikají
Nejen uvnitř
for-each. Obecně se nikde v XSLT nemůžete odkazovat ani na výstup ani na nějaký vámi definovaný dynamický stav. XSLT je záměrně dělané tak, aby v něm neexistoval žádný uživatelem definovaný stav.
Dá se udělat to, že výstup XSLT transformace proženete další transformací (klidně i v rámci jedné šablony), ale je to komplikace, efektivita zpracování tím dostává na frak.
Citace od: ZAJDAN kdy 18. 07. 2021, 12:05:01
ale musím se odkazovat na vstupní XML strukturu kterou má cyklus v selektu. V mém případě bych tedy v xsl:number ukazoval na ResultSet/Row, etc a to mi asi nepomůže.
Vždyť jsem to ukazoval, že
xsl:number může odkazovat přímo na
Pack. Pomocí atributu
count si necháte očíslovat všechny uzly
Pack, pomocí
select si pak jen vyzvednete číslo konkrétního
Packu.
Citace od: Filip Jirsák kdy 18. 07. 2021, 13:26:24
...
1) Celá ta věc používá XSLT 1.0 (SAP IntegrationFramework 2.0)
2) Píšete, že se nemohu odkazovat na dynamicky vznikající obsah a následně píšete, že se mohu odkazovat na Pack, ale právě ten Pack v ten moment dynamicky vzniká.
Citace od: Kit kdy 18. 07. 2021, 11:55:43
Atribut select tam skutečně není, ale jsou tam atributy from a value, které plní tuto funkci.
from a
value mají úplně jinou funkci – slouží pro víceúrovňové číslování, kdybyste chtěl třeba číslovat jako ,,Kapitola 14.3".
Citace od: ZAJDAN kdy 18. 07. 2021, 13:31:19
Celá ta věc používá XSLT 1.0 (SAP IntegrationFramework 2.0)
Tak to teda hodně štěstí... Nicméně atribut
count pro
xsl:number je už v XSLT 1.0, takže by to mohlo jít. Není tam atribut
select, takže když nepoužijete
value, vztahuje se k aktuálnímu uzlu, ale to by nemusel být problém.
Citace od: ZAJDAN kdy 18. 07. 2021, 13:31:19
Píšete, že se nemohu odkazovat na dynamicky vznikající obsah a následně píšete, že se mohu odkazovat na Pack, ale právě ten Pack v ten moment dynamicky vzniká.
To jsem asi popletl ty příklady tady. Odkazovat se můžete jen na vstupní dokument.
Citace od: ZAJDAN kdy 18. 07. 2021, 10:36:03
Palety iterují jen na sobě, boxy jen v jednom kole.
Počítá mi to takto:
<Pack>
<Type>Pallet</Type>
<ID>11</ID>
<Sequence>1</Sequence>
</Pack>
<Pack>
<Type>Box</Type>
<Child>aaa</Child>
<Parent>1</Parent>
<Sequence>2</Sequence>
</Pack>
<Pack>
<Type>Box</Type>
<Child>bbb</Child>
<Parent>1</Parent>
<Sequence>2</Sequence>
</Pack>
<Pack>
<Type>Pallet</Type>
<ID>10</ID>
<Sequence>2</Sequence>
</Pack>
<Pack>
<Type>Box</Type>
<Child>ccc</Child>
<Parent>2</Parent>
<Sequence>3</Sequence>
</Pack>
<Pack>
<Type>Box</Type>
<Child>ddd</Child>
<Parent>2</Parent>
<Sequence>3</Sequence>
</Pack>
<Pack>
<Type>Pallet</Type>
<ID>6</ID>
<Sequence>3</Sequence>
</Pack>
<Pack>
<Type>Box</Type>
<Child>zzz</Child>
<Parent>3</Parent>
<Sequence>4</Sequence>
</Pack>
Předpokládám, že jsi si ověřil, že tam máš správný kód a nedošlo k nějaké chybě při přepisu nebo něco podobného, takže mě zajímá: Co za nástroj to zpracovává? Zkoušel jsem Xalan, zkoušel jsem https://xslttest.appspot.com/, tudíž za mě to považuji za vyřešené.
Citace od: BoneFlute kdy 18. 07. 2021, 14:59:08
tudíž za mě to považuji za vyřešené.
Ty vaše příklady jsou krásná ukázka toho, že lidé často píšou pořád v jednom programovacím jazyce, bez ohledu na to, jakou syntaxi zrovna používají. Ten váš příklad je C, nebo Python, nebo jakýkoli imperativní jazyk, akorát napsaný pomocí XSLT syntaxe.
Citace od: Filip Jirsák kdy 18. 07. 2021, 15:26:51
Citace od: BoneFlute kdy 18. 07. 2021, 14:59:08
tudíž za mě to považuji za vyřešené.
Ty vaše příklady jsou krásná ukázka toho, že lidé často píšou pořád v jednom programovacím jazyce, bez ohledu na to, jakou syntaxi zrovna používají. Ten váš příklad je C, nebo Python, nebo jakýkoli imperativní jazyk, akorát napsaný pomocí XSLT syntaxe.
Mýlíš se, jako vždy, ale to nevadí.
Citace od: BoneFlute kdy 18. 07. 2021, 15:59:03
Citace od: Filip Jirsák kdy 18. 07. 2021, 15:26:51
Citace od: BoneFlute kdy 18. 07. 2021, 14:59:08
tudíž za mě to považuji za vyřešené.
Ty vaše příklady jsou krásná ukázka toho, že lidé často píšou pořád v jednom programovacím jazyce, bez ohledu na to, jakou syntaxi zrovna používají. Ten váš příklad je C, nebo Python, nebo jakýkoli imperativní jazyk, akorát napsaný pomocí XSLT syntaxe.
Mýlíš se, jako vždy, ale to nevadí.
Nemýlí se. XSLT se fakt používá jinak.
Pokud platí, že na vstupu jsou řádky správně seřazené, pak bude fungovat např. toto:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<Workbook>
<xsl:apply-templates select="ResultsSet/ResultSet[1]/Row"/>
</Workbook>
</xsl:template>
<xsl:template match="/ResultsSet/ResultSet[1]/Row">
<xsl:variable name="id" select="Parent"/>
<Pack>
<Type>Pallet</Type>
<ID><xsl:value-of select="$id" /></ID>
<Sequence><xsl:value-of select="count(preceding-sibling::Row) + count(/ResultsSet/ResultSet[2]/Row[Parent = $id][1]/preceding-sibling::Row) + 1" /></Sequence>
</Pack>
<xsl:apply-templates select="/ResultsSet/ResultSet[2]/Row[Parent=$id]"/>
</xsl:template>
<xsl:template match="/ResultsSet/ResultSet[2]/Row">
<xsl:variable name="current" select="."/>
<Pack>
<Type>Box</Type>
<ID><xsl:value-of select="Child" /></ID>
<Sequence><xsl:value-of select="count(preceding-sibling::Row) + count(/ResultsSet/ResultSet[1]/Row[Parent = $current/Parent]/preceding-sibling::Row) + 2" /></Sequence>
<Parent><xsl:value-of select="Parent" /></Parent>
</Pack>
</xsl:template>
</xsl:stylesheet>
BoneFlute si může všimnout, že to není imperativní program, takže tam není žádná pojmenovaná funkce (šablona) ani žádný cyklus.
Citace od: Filip Jirsák kdy 18. 07. 2021, 16:11:44
Pokud platí, že na vstupu jsou řádky správně seřazené, pak bude fungovat např. toto:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<Workbook>
<xsl:apply-templates select="ResultsSet/ResultSet[1]/Row"/>
</Workbook>
</xsl:template>
<xsl:template match="/ResultsSet/ResultSet[1]/Row">
<xsl:variable name="id" select="Parent"/>
<Pack>
<Type>Pallet</Type>
<ID><xsl:value-of select="$id" /></ID>
<Sequence><xsl:value-of select="count(preceding-sibling::Row) + count(/ResultsSet/ResultSet[2]/Row[Parent = $id][1]/preceding-sibling::Row) + 1" /></Sequence>
</Pack>
<xsl:apply-templates select="/ResultsSet/ResultSet[2]/Row[Parent=$id]"/>
</xsl:template>
<xsl:template match="/ResultsSet/ResultSet[2]/Row">
<xsl:variable name="current" select="."/>
<Pack>
<Type>Box</Type>
<ID><xsl:value-of select="Child" /></ID>
<Sequence><xsl:value-of select="count(preceding-sibling::Row) + count(/ResultsSet/ResultSet[1]/Row[Parent = $current/Parent]/preceding-sibling::Row) + 2" /></Sequence>
<Parent><xsl:value-of select="Parent" /></Parent>
</Pack>
</xsl:template>
</xsl:stylesheet>
BoneFlute si může všimnout, že to není imperativní program, takže tam není žádná pojmenovaná funkce (šablona) ani žádný cyklus.
Negeneruje to požadovaný výsledek. Nesedí Parent.
Jestli chceš být užitečný, zkus se pochlubit jak se dělá to "Dá se udělat to, že výstup XSLT transformace proženete další transformací (klidně i v rámci jedné šablony)". To neumím, to mě zajímá.
Citace od: BoneFlute kdy 18. 07. 2021, 16:43:34
Negeneruje to požadovaný výsledek. Nesedí Parent.
Ono se tu těžko hledá, co má být vlastně vstupem a co výstupem, když je to rozcourané po různých komentářích. Místo zbytečných keců jste takovou trivialitu mohl opravit.
Oprava je zde:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<Workbook>
<xsl:apply-templates select="ResultsSet/ResultSet[1]/Row"/>
</Workbook>
</xsl:template>
<xsl:template match="/ResultsSet/ResultSet[1]/Row">
<xsl:variable name="id" select="Parent"/>
<Pack>
<Type>Pallet</Type>
<ID><xsl:value-of select="$id" /></ID>
<Sequence><xsl:value-of select="count(preceding-sibling::Row) + count(/ResultsSet/ResultSet[2]/Row[Parent = $id][1]/preceding-sibling::Row) + 1" /></Sequence>
</Pack>
<xsl:apply-templates select="/ResultsSet/ResultSet[2]/Row[Parent=$id]"/>
</xsl:template>
<xsl:template match="/ResultsSet/ResultSet[2]/Row">
<xsl:variable name="current" select="."/>
<Pack>
<Type>Box</Type>
<ID><xsl:value-of select="Child" /></ID>
<Sequence><xsl:value-of select="count(preceding-sibling::Row) + count(/ResultsSet/ResultSet[1]/Row[Parent = $current/Parent]/preceding-sibling::Row) + 2" /></Sequence>
<Parent><xsl:value-of select="count(preceding-sibling::Row[Parent != $current/Parent]) + count(/ResultsSet/ResultSet[1]/Row[Parent = $current/Parent]/preceding-sibling::Row) + 1" /></Parent>
</Pack>
</xsl:template>
</xsl:stylesheet>
Citace od: BoneFlute kdy 18. 07. 2021, 16:43:34
Jestli chceš být užitečný, zkus se pochlubit jak se dělá to "Dá se udělat to, že výstup XSLT transformace proženete další transformací (klidně i v rámci jedné šablony)". To neumím, to mě zajímá.
Považuji za užitečné to, že jsem tazateli poradil, jak vyřešit jeho problém.
Citace od: Filip Jirsák kdy 18. 07. 2021, 17:49:20
Citace od: BoneFlute kdy 18. 07. 2021, 16:43:34
Negeneruje to požadovaný výsledek. Nesedí Parent.
Místo zbytečných keců
Omlouvám se. Napsat to kratšeji mi už přišlo hulvátské.
Citace od: ZAJDAN kdy 18. 07. 2021, 10:36:03
...
Co říkáš, na toto řešení? Toto ti funguje?
Citace od: BoneFlute kdy 18. 07. 2021, 19:30:28
....
Zítra to s čistou hlavou znovu zkusím.
Citace od: Filip Jirsák kdy 18. 07. 2021, 17:49:20
....
Docela se stydím přiznat, že tento standardní přístup jsem při používání XSLT nevyužíval a všude používám for-each.
Zkouším tu Vaši variantu, ale neiteruje mi to. Vytvoří to jen jednu paletu a jeden box.
Citace od: ZAJDAN kdy 18. 07. 2021, 23:31:44
Zkouším tu Vaši variantu, ale neiteruje mi to. Vytvoří to jen jednu paletu a jeden box.
Já jsem to zkoušel na datech z komentáře č. 4 (https://forum.root.cz/index.php?topic=25002.msg354726#msg354726) a fungovalo to. Zkoušel jsem to v Oxygenu (https://www.oxygenxml.com), který interně používá Saxon (https://www.saxonica.com/welcome/welcome.xml). Buď ta vstupní data vypadají jinak, nebo to, na čem to spouštíte, není XSLT procesor, ale jenom nějaká nepovedená napodobenina. Protože to, že
xsl:apply-templates se aplikuje na všechny uzly odpovídající selektoru, je úplně tou nejzákladnější vlastností XSLT.
Citace od: Filip Jirsák kdy 19. 07. 2021, 10:58:15
Citace od: ZAJDAN kdy 18. 07. 2021, 23:31:44
Zkouším tu Vaši variantu, ale neiteruje mi to. Vytvoří to jen jednu paletu a jeden box.
Já jsem to zkoušel na datech z komentáře č. 4 (https://forum.root.cz/index.php?topic=25002.msg354726#msg354726) a fungovalo to. Zkoušel jsem to v Oxygenu (https://www.oxygenxml.com), který interně používá Saxon (https://www.saxonica.com/welcome/welcome.xml). Buď ta vstupní data vypadají jinak, nebo to, na čem to spouštíte, není XSLT procesor, ale jenom nějaká nepovedená napodobenina. Protože to, že xsl:apply-templates se aplikuje na všechny uzly odpovídající selektoru, je úplně tou nejzákladnější vlastností XSLT.
Zkusil jsem to v
xsltproc a také to jede bez potíží. Do elementu
Sequence postupně vygeneruje hodnoty 1-8.
Pánové moc díky za Vaše rady a nápady, které jste mi poskytli.
On ten Integrační framework od SAPu je taková parní lokomotiva :) a ne všechno tam funguje standardně.
Každopádně si nejsem jist, zda mohu 'apply-templates' použít uvnitř volané template.
<xsl:template match="/">
<vpf:Msg>
<xsl:copy-of select="/vpf:Msg/@*"></xsl:copy-of>
<xsl:copy-of select="/vpf:Msg/vpf:Header"></xsl:copy-of>
<vpf:Body>
<xsl:copy-of select="/vpf:Msg/vpf:Body/*"></xsl:copy-of>
<vpf:Payload Role="X" id="{$atom}">
<xsl:call-template name="transform"></xsl:call-template>
</vpf:Payload>
</vpf:Body>
</vpf:Msg>
</xsl:template>
<xsl:template name="transform">
....
....
.....
<xsl:template match="/">
<Pack>
<xsl:apply-templates select="/vpf:Msg/vpf:Body/vpf:Payload[@id='CallSQL']/jdbc:ResultSets/jdbc:ResultSet[3]/jdbc:Row"></xsl:apply-templates>
</Pack>
</xsl:template>
</xsl:template>
Citace od: ZAJDAN kdy 20. 07. 2021, 10:37:25
Každopádně si nejsem jist, zda mohu 'apply-templates' použít uvnitř volané template.
Ano, je možné ho použít uvnitř a funguje i rekurzívně.
Citace od: ZAJDAN kdy 20. 07. 2021, 10:37:25
Pánové moc díky za Vaše rady a nápady, které jste mi poskytli.
On ten Integrační framework od SAPu je taková parní lokomotiva :) a ne všechno tam funguje standardně.
Každopádně si nejsem jist, zda mohu 'apply-templates' použít uvnitř volané template.
jj, můžeš, ale v tvém případě platí - to prostě zkus, je-li ten SAP tak nestandardní.
Citace od: ZAJDAN kdy 20. 07. 2021, 10:37:25
Pánové moc díky za Vaše rady a nápady, které jste mi poskytli.
On ten Integrační framework od SAPu je taková parní lokomotiva :) a ne všechno tam funguje standardně.
Každopádně si nejsem jist, zda mohu 'apply-templates' použít uvnitř volané template.
<xsl:template name="transform">
....
....
.....
<xsl:template match="/">
<Pack>
<xsl:apply-templates select="/vpf:Msg/vpf:Body/vpf:Payload[@id='CallSQL']/jdbc:ResultSets/jdbc:ResultSet[3]/jdbc:Row"></xsl:apply-templates>
</Pack>
</xsl:template>
</xsl:template>
Utčitě není možné v XSLT mít
xsl:template uvnitř jiného
xsl:template. Ten váš příklad by měl vypadat např. takto:
<xsl:template match="/">
<vpf:Msg>
<xsl:copy-of select="/vpf:Msg/@*"></xsl:copy-of>
<xsl:copy-of select="/vpf:Msg/vpf:Header"></xsl:copy-of>
<vpf:Body>
<xsl:copy-of select="/vpf:Msg/vpf:Body/*"></xsl:copy-of>
<vpf:Payload Role="X" id="{$atom}">
<xsl:apply-templates select="/vpf:Msg/vpf:Body/vpf:Payload[@id='CallSQL']" />
</vpf:Payload>
</vpf:Body>
</vpf:Msg>
</xsl:template>
<xsl:template match="/vpf:Msg/vpf:Body/vpf:Payload[@id='CallSQL']">
<Pack>
<xsl:apply-templates select="jdbc:ResultSets/jdbc:ResultSet[3]/jdbc:Row" />
</Pack>
</xsl:template>
@BoneFlute
tak verzi co jsi mi poslal už jsem zprovoznil
@Filip Jirsák
šablony určitě také zkusím, snad se k tomu dnes dostanu
všem díky!
Citace od: ZAJDAN kdy 21. 07. 2021, 09:54:45
@BoneFlute
tak verzi co jsi mi poslal už jsem zprovoznil
@Filip Jirsák
šablony určitě také zkusím, snad se k tomu dnes dostanu
všem díky!
Rádo se stalo. V čem byl problém?
Citace od: BoneFlute kdy 22. 07. 2021, 17:31:30
Rádo se stalo. V čem byl problém?
u jednoho elementu mi chyběl namespace
jdbc:Row