2012-06-18 21 views
10

Pracuję nad XSLT, gdzie muszę zaimplementować coś w następujący sposób. Moja próbka XML źródłowa wygląda następująco.Implementowanie wartości klucza w XSLT

<?xml version="1.0" encoding="ISO-8859-1"?> 
    <catalog> 
     <cd> 
      <title>A</title> 
      <title>B</title> 
      <title>C</title> 
     </cd> 
    </catalog> 

Rozważmy istnieje jakiś klucz lista para wartość jest tam.

Key   Value 
    A   Algebra 
    B   Biology 
    C   Chemistry 
    D   Data Analysis 
    ---   --- 

    ----  --- 

muszę napisać XSLT takie, że dla każdego wystąpieniu kluczowego „a”, trzeba zastąpić odpowiednią wartością.

Muszę również wymienić listę par Klucz wartości w tym samym XSLT. Wyjście próbki:

<Data> 
    <Subject>Algebra</Subject> 
    <Subject>Biology</Subject> 
    <Subject>Chemistry</Subject> 
</Data> 

Może ktoś mi pomóc jak to zrobić.

Dziękuję.

Odpowiedz

16

I. Proste XSLT 1.0 Rozwiązanie

Ta przemiana:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:my="my:my"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<my:codes> 
    <code key="A" value="Algebra"/> 
    <code key="B" value="Biology"/> 
    <code key="C" value="Chemistry"/> 
    <code key="D" value="Data Analysis"/> 
</my:codes> 

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

<xsl:template match= 
    "title/text()[. = document('')/*/my:codes/*/@key]"> 

    <xsl:value-of select= 
    "document('')/*/my:codes/*[@key=current()]/@value"/> 
</xsl:template> 
</xsl:stylesheet> 

po naniesieniu na dostarczonych dokumentów XML:

<catalog> 
    <cd> 
     <title>A</title> 
     <title>B</title> 
     <title>C</title> 
    </cd> 
</catalog> 

produkuje chciał, poprawny wynik:

<catalog> 
    <cd> 
     <title>Algebra</title> 
     <title>Biology</title> 
     <title>Chemistry</title> 
    </cd> 
</catalog> 

Wyjaśnienie:

Jest to standardowy sposób z tym węzeł inline XML jako element globalnej (element dzieckiem xsl:stylesheet), który należy do (niepusty) przestrzeń nazw, inna niż przestrzeń nazw xsl.


II. Bardziej wydajny XSLT 1.0 rozwiązanie, za pomocą klawiszy:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:my="my:my"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <my:codes> 
     <code key="A" value="Algebra"/> 
     <code key="B" value="Biology"/> 
     <code key="C" value="Chemistry"/> 
     <code key="D" value="Data Analysis"/> 
    </my:codes> 

    <xsl:key name="kCodeByName" match="code" use="@key"/> 

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

    <xsl:template match= 
     "title/text()[. = document('')/*/my:codes/*/@key]"> 

     <xsl:variable name="vCur" select="."/> 

     <xsl:for-each select="document('')"> 
      <xsl:value-of select= 
      "key('kCodeByName', $vCur)/@value"/> 
     </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

kiedy ta transformacja jest stosowane na tym samym dokumencie XML (powyżej), tak samo poprawne, chciał wynik jest produkowany:

<catalog> 
    <cd> 
     <title value="Algebra"/> 
     <title value="Biology"/> 
     <title value="Chemistry"/> 
    </cd> 
</catalog> 

Objaśnienie::

Dostęp do danych za pomocą funkcji key() jest zwykle podrzędny - często O (1) i jest wyjątkowo fas ter wyszukiwania liniowego (co jest ważne, jeśli liczba przeszukiwanych węzłów jest duża).

Uzyskiwanie dostępu do węzła jednego dokumentu za pośrednictwem indeksu (xsl:key) podczas przetwarzania węzła innego dokumentu jest możliwe, jeśli dokument zawierający węzeł, który ma zostać sprawdzony, jest bieżącym dokumentem. Aby uzyskać dostęp do węzłów z innego dokumentu, jego katalog główny (lub węzeł zainteresowania musi być zapisany i odwoływany do zmiennej.)


III. XSLT 2.0 rozwiązanie:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:my="my:my"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:variable name="vCodes"> 
    <codes> 
    <code key="A" value="Algebra"/> 
    <code key="B" value="Biology"/> 
    <code key="C" value="Chemistry"/> 
    <code key="D" value="Data Analysis"/> 
    </codes> 
</xsl:variable> 

<xsl:key name="kCodeByName" match="code" use="string(@key)"/> 

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

<xsl:template match= 
    "title/text()[key('kCodeByName', ., $vCodes)]"> 

    <xsl:sequence select= 
    "key('kCodeByName', ., $vCodes)/@value"/> 
</xsl:template> 
</xsl:stylesheet> 

kiedy ta transformacja jest stosowane na tym samym dokumencie XML (powyżej), tak samo poprawne, chciał wynik jest produkowany:

<catalog> 
    <cd> 
     <title value="Algebra"/> 
     <title value="Biology"/> 
     <title value="Chemistry"/> 
    </cd> 
</catalog> 

wyjaśnienie:

Prawie tak samo, jak wydajne rozwiązanie XSLT 1.0, ale:

  1. W XSLT 2.0 wzór dopasowania szablonu może zawierać odniesienie do zmiennej.

  2. W XSLT 2.0 nie ma potrzeby akrobatycznych sztuczek manipulacji prąd i indeksowane dokumenty - 3rd argumentu funkcji key() jest określenie drzewa, którego indeks w użyciu.

+0

Dziękuję za odpowiedź. – Patan

+0

@ Użytkownik222: Nie ma za co. –

+0

@Dimitre Czy możemy nazwać szablon w rozwiązaniu III. XSLT 2.0 w innym szablonie. Jeśli tak, proszę dać mi znać, w jaki sposób? –

Powiązane problemy