2009-10-26 16 views
6

Załóżmy, że przekształcam quiz wielokrotnego wyboru z dowolnego formatu XML na HTML. Każdy wybór będzie reprezentowany jako znacznik HTML <li> w dokumencie wynikowym. Dla każdego wyboru chcę dodać kod HTML class z correct do <li>, jeśli ten wybór był prawidłową odpowiedzią. Dodatkowo, jeśli ten wybór został wybrany przez użytkownika, chcę dodać klasę submitted do <li>. W konsekwencji, jeśli wybór jest poprawny, , a także przedłożony, powinien mieć class z correct submitted.Czy istnieje elegancki sposób dodawania wielu klas HTML za pomocą XSLT?

O ile mi wiadomo, wartości atrybutów oddzielonych białą przestrzenią nie są częścią modelu danych XML i dlatego nie można ich bezpośrednio utworzyć za pomocą XSLT. Mam jednak wrażenie, że jest lepszy sposób na to, niż zaśmiecanie kodu jednym warunkiem dla każdej możliwej kombinacji klas (co byłoby do przyjęcia w tym przykładzie, ale nieporęczne w bardziej złożonych scenariuszach).

Jak mogę rozwiązać ten problem w elegancki sposób?

Przykład pożądanego rezultatu:

<p>Who trained Obi-Wan Kenobi?</p> 
<ul> 
    <li>Mace Windu</li> 
    <li class="correct submitted">Qui-Gon Jinn</li> 
    <li>Ki-Adi-Mundi</li> 
    <li>Yaddle</li> 
</ul> 

Odpowiedz

9

Po pierwsze, nic nie jest nie tak z białymi znakami w wartościach atrybutów w XML: z grubsza rzecz biorąc, attribute value normalization konwertuje znaki odstępu na spacje i zwija sąsiednie spacje na pojedynczą spację, gdy dokument jest parsowany, ale spacje są zdecydowanie dozwolone. EDYCJA: Zobacz poniżej, aby uzyskać więcej informacji na ten temat.

Podejście Matthew Wilsona nie obejmuje białych znaków między możliwymi wartościami, jak wspominasz w komentarzu do tego. Jednak jego podejście jest zasadniczo zdrowe. Ostatnim elementem układanki jest niechęć do nadmiarowych przestrzeni: można je wyeliminować za pomocą funkcji XPath normalize-space.

Poniższy arkusz stylów umieszcza wszystkie bity razem - zauważ, że nic nie robi z jego dokumentem wejściowym, więc dla celów testowania możesz uruchomić go na dowolnym dokumencie XML, a nawet samym sobie, aby sprawdzić, czy wyjście spełnia Twoje wymagania.

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:variable name="foo0" select="false()"/> 
    <xsl:variable name="bar0" select="true()"/> 

    <xsl:variable name="foo1" select="true()"/> 
    <xsl:variable name="bar1" select="false()"/> 

    <xsl:variable name="foo2" select="true()"/> 
    <xsl:variable name="bar2" select="true()"/> 

    <xsl:template match="/"> 

    <xsl:variable name="foobar0"> 
     <xsl:if test="$foo0"> foo</xsl:if> 
     <xsl:if test="$bar0"> bar</xsl:if> 
    </xsl:variable> 

    <xsl:variable name="foobar1"> 
     <xsl:if test="$foo1"> foo</xsl:if> 
     <xsl:if test="$bar1"> bar</xsl:if> 
    </xsl:variable> 

    <xsl:variable name="foobar2"> 
     <xsl:if test="$foo2"> foo</xsl:if> 
     <xsl:if test="$bar2"> bar</xsl:if> 
    </xsl:variable> 

    <li> 
     <xsl:attribute name="class"> 
     <xsl:value-of select="normalize-space($foobar0)"/> 
     </xsl:attribute> 
    </li> 
    <li> 
     <xsl:attribute name="class"> 
     <xsl:value-of select="normalize-space($foobar1)"/> 
     </xsl:attribute> 
    </li> 
    <li> 
     <xsl:attribute name="class"> 
     <xsl:value-of select="normalize-space($foobar2)"/> 
     </xsl:attribute> 
    </li> 

    </xsl:template> 
</xsl:stylesheet> 

Edycja: nawiązaniu do kwestii przestrzeniach oddzielających elementów dyskretnych w zakresie wartości atrybutu: XML Spec określa liczbę możliwych ważnych konstrukcji, takich jak attribute types IDREFS i NMTOKENS. Pierwszy przypadek odpowiada produkcji Names, a drugi przypadek odpowiada produkcji NMTokens; obie te produkcje są zdefiniowane jako zawierające wiele wartości odpowiedniego typu, ograniczonych spacjami.Listy wartości rozdzielone spacjami jako wartość pojedynczego atrybutu są nieodłącznym składnikiem zestawu informacji XML.

+0

Właściwie, moim punktem na temat wartości atrybutów rozdzielonych białymi znakami jest to, że XML nie rozpoznaje ich jako odrębnych wartości - jest to jeden długi ciąg znaków (chyba że przeoczyłem część XML). To jest powód, dla którego zawsze czuję się lekko brudny, gdy używam atrybutów klasowych. To powiedziawszy, zdaję sobie sprawę, że o wiele łatwiej jest nam koderom, aby oddzielić klasy od spacji, zamiast wpychać w garść 'elementów podrzędnych' 'wszędzie. – Jakob

+2

@Jakob: Dodałem więcej szczegółów na temat rozdzielonych spacjami list wartości tworzących jedną wartość atrybutu na końcu mojej odpowiedzi. – NickFitz

5

Off szczycie mojej głowie, można zbudować listę oddzielonych spacjami z czymś takim:

<li> 
    <xsl:attribute name="class"> 
     <xsl:if cond="...">correct</xsl:if> 
     <xsl:if cond="...">submitted</xsl:if> 
    </xsl:attribute> 
</li> 
+0

To nie działa (przynajmniej nie używając PHP). Nie ma tam białej przestrzeni poza tym, co otacza elementy 'if', i to nie ma wpływu na wyjście (trzeba by użyć do tego elementów' text'). Oczywiście, mógłbym użyć tego rozwiązania i po prostu dodać spację po każdej możliwej nazwie klasy, ale to doprowadziłoby do zbędnych przestrzeni i wydaje się bardziej zagracone niż to, co powinno być konieczne. – Jakob

+1

Użyłem go z powodzeniem, więc może to różnica w procesorach XSLT, co do tego, co robią z białymi spacji w samym pliku XSLT. –

+2

Czy 'cond' nie powinno być' testem'? – Maarten

1

O ile mi Wiem, że wartości atrybutów oddzielonych białą przestrzenią nie są częścią modelu danych XML, a zatem nie można ich bezpośrednio utworzyć za pomocą XSLT

Jeśli nie dokonujesz konwersji do języka XML (którego HTML nie jest, XHTML jest), nie powinieneś martwić się o ważność XML XSLT ouput. To może być wszystko, i nie musi być zgodne z XML!

+0

Nie mówię, że wartości atrybutów oddzielonych spacjami są nieprawidłowe XML, tyle że nie istnieją (według mojej wiedzy) konstrukcje XSLT, które je generują. – Jakob

Powiązane problemy