Как это сделать, если еще в <xsl: next-iteration> <xsl: with-param - PullRequest
0 голосов
/ 23 января 2019

Я пытаюсь выполнить условие If в xsl: with-param в xsl: next-iteration.

Мой xml такой, как показано ниже:

<?xml version="1.0" encoding="UTF-8"?>
<XmlRoot>
   <Rec>
      <pD>20181221</pD>
      <gl>00001</gl>
      <le_Ac>29246</le_Ac>
      <eid>009158099</eid>
      <tA>9.61</tA>
   </Rec>
   <Rec>
      <pD>20181221</pD>
      <gl>00001</gl>
      <le_Ac>29246</le_Ac>
      <eid>009158099</eid>
      <tA>10.61</tA>
   </Rec>   
   <Rec>
      <pD>20181221</pD>
      <gl>00001</gl>
      <le_Ac>60300</le_Ac>
      <eid>909154343</eid>
      <tA>11.61</tA>
   </Rec>   
   <Rec>
      <pD>20181221</pD>
      <gl>00001</gl>
      <le_Ac>60300</le_Ac>
      <eid>909154343</eid>
      <tA>12.61</tA>
   </Rec>
</XmlRoot>

И мой xslt, как показано ниже, я пытаюсь передать очень большой xml.

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

    <xsl:mode streamable="yes"/>

    <xsl:output method="text"/>

    <xsl:template match="/">
        <xsl:iterate select="XmlRoot/Rec">
            <xsl:param name="mapAllKeys" as="map(xs:string, xs:float?)" select="map{}"/>
            <xsl:param name="map29246" as="map(xs:string, xs:float?)" select="map{}"/>
            <xsl:param name="mapDummy" as="map(xs:string, xs:float?)" select="map{}"/>
            <xsl:on-completion>
                <!--<xsl:value-of select="map:keys($mapAllKeys)!(. || concat('&quot;',',','&quot;') || $mapAllKeys(.))" separator="&#10;"/>-->
                    <xsl:for-each 
                        select="map:for-each($mapAllKeys,function ($k, $v){$k})">
                            <xsl:value-of select="."/>
                        <xsl:value-of select="'&#10;'"/>
                        <xsl:value-of select="if(map:contains($map29246,.)) then map:get($map29246,.) else 0"/>
                        <xsl:value-of select="'&#10;'"/>
                    </xsl:for-each>
               </xsl:on-completion>
            <xsl:variable name="current-entry" select="copy-of()"/>
            <xsl:variable name="pDt">
                <xsl:choose>
                    <xsl:when test="$current-entry/pD = ''"><xsl:value-of select="$current-entry/aD"/></xsl:when>
                    <xsl:otherwise><xsl:value-of select="$current-entry/pD"/></xsl:otherwise>
                </xsl:choose>
            </xsl:variable>
            <xsl:variable name="key" select="$current-entry/concat(pD, eid, gl,na)"/>
            <xsl:next-iteration>
                <xsl:with-param name="mapAllKeys"
                    select="
                    if (map:contains($mapAllKeys, xs:string($key))) then
                        map:put($mapAllKeys, xs:string($key), map:get($mapAllKeys, xs:float(1.0)))
                    else
                        map:put($mapAllKeys, xs:string($key), xs:float(1.0))"
                />

                <xsl:with-param name="map29246"
                    select="
                    if($current-entry/le_Ac = '29246') then
                       if (map:contains($map29246, xs:string($key))) then
                          map:put($map29246, xs:string($key), map:get($map29246, xs:string($key)) + xs:float($current-entry/tA))
                       else
                          map:put($map29246, xs:string($key), xs:float($current-entry/tA))
                    else
                    map:put($mapDummy, 'DUMMY', xs:float('0.0'))
                    "/>

            </xsl:next-iteration>
        </xsl:iterate>
    </xsl:template>

</xsl:stylesheet>

Основная проблема - код если ($ current-entry / le_Ac = '29246') тогда никогда не удовлетворяет.

Я хочу добавить на карту только когда le_Ac = 29246

Кроме того, он всегда запрашивает другую часть, во всяком случае, чтобы избежать другой части? Я пытаюсь использовать фиктивную карту, чтобы обойти ее.

любая помощь приветствуется! Спасибо!

1 Ответ

0 голосов
/ 23 января 2019

Что касается вопроса о том, чтобы ничего не добавлять на карту, я думаю, что в последнем else вместо map:put($mapDummy, 'DUMMY', xs:float('0.0')) я бы ожидал else $map29246.

Поскольку вы также пометили вопрос как , возможно, что вся проблема может быть решена с помощью

<xsl:template match="/">
    <xsl:for-each-group select="XmlRoot/Rec!map:merge(*!map { local-name() : string() })" composite="yes" group-by="?pD, ?eid, ?gl, ?na">
        <xsl:value-of select="string-join(current-grouping-key()), sum(current-group()[?le_Ac = '29246']?tA!xs:decimal(.))" separator="&#10;"/>
        <xsl:text>&#10;</xsl:text>
    </xsl:for-each-group>
</xsl:template>

Выход для вашего образца с Saxon 9.8.0.12 EE в oXygen равен

2018122100915809900001
20.22
2018122190915434300001
0

Другой подход был бы

<xsl:template match="/">
    <xsl:for-each-group select="XmlRoot/Rec!copy-of()" composite="yes" group-by="pD, eid, gl,na">
        <xsl:value-of select="string-join(current-grouping-key()), sum(current-group()[le_Ac = 29246]/tA)" separator="&#10;"/>
        <xsl:text>&#10;</xsl:text>
    </xsl:for-each-group>
</xsl:template>

Я не проводил никаких измерений с большими входами, чтобы увидеть, какой из них работает лучше или, по крайней мере, использует меньше памяти.

...