Mam taki arkusz xml:

<houses>
    <house number="1">
        <mainroom>
            <roomprice>5</roomprice>
            <roomtax>2</roomtax>
        </mainroom>
        <roompricefull>
            <price value="8"/>
        </roompricefull>
    </house>
    <house number="2">
        <mainroom>
            <roomprice>3</roomprice>
            <roomtax>1</roomtax>
        </mainroom>
        <roompricefull>
            <price value="7"/>
        </roompricefull>
    </house>
    <house number="3">
        <mainroom>
            <roomprice>9</roomprice>
            <roomtax>1</roomtax>
        </mainroom>
        <roompricefull>
            <price value="4"/>
        </roompricefull>
    </house>
    <house number="4">
        <mainroom>
            <roomprice>12</roomprice>
            <roomtax>3</roomtax>
        </mainroom>
        <roompricefull>
            <price value="6"/>
        </roompricefull>
    </house>
</houses>

Musiałem więc zmienić wartość atrybutu „value” w elemencie „price” w każdym z „domu” na sumę wartości „roomprice” i „roomtax”

Napisałem taką transformację xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template name="PriceChange" match="price[parent::roompricefull]">
        <xsl:copy>
            <xsl:variable name="sn" select="../../@number"/>
            <xsl:variable name="TaxValue" select="number(//house[@number=string($sn)]/mainroom/roomtax)"/>
            <xsl:variable name="BaseValue" select="number(//house[@number=string($sn)]/mainroom/roomprice)"/>
            <xsl:attribute name="value">
                <xsl:value-of select="string($TaxValue+$BaseValue)"/>
            </xsl:attribute>
            <!--xsl:for-each select="/houses/house">
            <xsl:sort select="houses/house[$sn]/roompricefull/@value"/>
        </xsl:for-each-->
        </xsl:copy> 
    </xsl:template>
</xsl:stylesheet>

Ale kiedy zacząłem pracować nad sortowaniem elementów „domu” według mojej nowej wartości, napotkałem problemy. Właściwie nie rozumiem, dlaczego to nie działa, więc skomentowałem mój ostatni z kilkudziesięciu przykładów w up code.

Mam to:

<houses>
    <house number="1">
        <mainroom>
            <roomprice>5</roomprice>
            <roomtax>2</roomtax>
        </mainroom>
        <roompricefull>
            <price value="7"/>
        </roompricefull>
    </house>
    <house number="2">
        <mainroom>
            <roomprice>3</roomprice>
            <roomtax>1</roomtax>
        </mainroom>
        <roompricefull>
            <price value="4"/>
        </roompricefull>
    </house>
    <house number="3">
        <mainroom>
            <roomprice>9</roomprice>
            <roomtax>1</roomtax>
        </mainroom>
        <roompricefull>
            <price value="10"/>
        </roompricefull>
    </house>
    <house number="4">
        <mainroom>
            <roomprice>12</roomprice>
            <roomtax>3</roomtax>
        </mainroom>
        <roompricefull>
            <price value="15"/>
        </roompricefull>
    </house>
</houses>

Ale oczekiwany wynik to:

<houses>
    <house number="4">
        <mainroom>
            <roomprice>12</roomprice>
            <roomtax>3</roomtax>
        </mainroom>
        <roompricefull>
            <price value="15"/>
        </roompricefull>
    </house>   
    <house number="3">
        <mainroom>
            <roomprice>9</roomprice>
            <roomtax>1</roomtax>
        </mainroom>
        <roompricefull>
            <price value="10"/>
        </roompricefull>
    </house>
    <house number="1">
        <mainroom>
            <roomprice>5</roomprice>
            <roomtax>2</roomtax>
        </mainroom>
        <roompricefull>
            <price value="7"/>
        </roompricefull>
    </house>
    <house number="2">
        <mainroom>
            <roomprice>3</roomprice>
            <roomtax>1</roomtax>
        </mainroom>
        <roompricefull>
            <price value="4"/>
        </roompricefull>
    </house>
</houses>

Byłoby wspaniale, gdybyś mógł mi pomóc w sortowaniu i wyjaśnianiu, dlaczego mój przykład nie działa. Wygląda na to, że nie rozumiem znaczenia , ale wszystko, co znajduję, mówi mi o jego użyciu bez żadnego wyjaśnienia. Z góry dziękuję.

3
lmhs 17 czerwiec 2011, 21:30
1
Rozważ opublikowanie próbki wyjściowej, którą chcesz utworzyć dla próbki wejściowej za pomocą XSLT.
 – 
Martin Honnen
17 czerwiec 2011, 21:41

2 odpowiedzi

Najlepsza odpowiedź

byłoby wspaniale, gdybyś pomógł mi w sortowaniu

To jest prawidłowe podejście XSLT 1.0.

Zwróć uwagę na prawidłowe użycie xsl:sort, które wymaga:

  • typ danych do określenia, jako ciąg domyślny, podczas gdy potrzebujemy tutaj liczba
  • najlepsze wykorzystanie sortowania wewnątrz xsl:apply-templates
  • zastosowanie sortowania z kluczami sortowania dokumentu wejściowego połączonymi zgodnie z wymaganiami (suma).
  • należy również określić porządek sortowania jako domyślny ascending

    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="houses">
       <xsl:copy>
        <xsl:apply-templates select="house">
            <xsl:sort select="mainroom/roomprice + mainroom/roomtax" 
             data-type="number"
             order="descending"/>
        </xsl:apply-templates>
       </xsl:copy>
    </xsl:template>
    
    <xsl:template match="price/@value">
        <xsl:value-of select="
            ../../../mainroom/roomprice 
            + 
            ../../../mainroom/roomtax"/>
    </xsl:template>
    


wyjaśnienie, dlaczego mój przykład nie działa

Twoja transformacja nie działa głównie dlatego, że próbujesz posortować elementy w niewłaściwym kontekście (wewnątrz szablonu pasującego do głębokiego elementu potomnego w drzewie). Ponadto:

  • próbujesz posortować, wskazując klucz sortowania według bezwzględnego wzorca XPath.
  • nie określasz potrzebnych xsl:sort atrybutów
  • chciałbyś, aby końcowe elementy były posortowane według wartości obliczonej później i nieobecnej w dokumencie wejściowym. To nie jest właściwe podejście. Należy zawsze używać wartości obecnych w dokumencie wejściowym, ostatecznie łącząc je poprawnie.
4
Emiliano Poggi 18 czerwiec 2011, 01:38
Dla wyczerpującej odpowiedzi. Naprawdę mi pomogłeś.
 – 
lmhs
18 czerwiec 2011, 15:27

Sortuj według nowej ceny:

<xsl:template match="/">
  <xsl:for-each select="house">
    <xsl:sort select="mainroom/roomprice + mainroom/roomtax"/>
    <xsl:apply-templates select="."/>
  </xsl:for-each>
</xsl:template>

Jak wcześniej:

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

Dostosuj cenę w wynikach:

<xsl:template match="roompricefull">
  <roompricefull>
    <price value="{../mainroom/roomprice + ../mainroom/roomtax}"/>
  </roompricefull>
</xsl:template>
0
AtnNn 17 czerwiec 2011, 21:44
Nawet jeśli podejście jest poprawne, istnieje zbyt wiele nieścisłości, które sprawiają, że ta odpowiedź jest całkowicie błędna.
 – 
Emiliano Poggi
18 czerwiec 2011, 01:41