2008-09-15 12 views
8

Biorąc pod uwagę następujące XML:Mecz warunkowo na bieżącą wartość węzeł

<current> 
    <login_name>jd</login_name> 
</current> 
<people> 
    <person> 
    <first>John</first> 
    <last>Doe</last> 
    <login_name>jd</login_name> 
    </preson> 
    <person> 
    <first>Pierre</first> 
    <last>Spring</last> 
    <login_name>ps</login_name> 
    </preson> 
</people> 

Jak mogę uzyskać „John Doe” od wewnątrz bieżącego/login dopasowującego?

Próbowałem następujące:

<xsl:template match="current/login_name"> 
    <xsl:value-of select="../people/first[login_name = .]"/> 
    <xsl:text> </xsl:text> 
    <xsl:value-of select="../people/last[login_name = .]"/> 
</xsl:template> 

Odpowiedz

10

bym zdefiniować klucz do indeksu ludu

<xsl:key name="people" match="person" use="login_name" /> 

Używając klucza tutaj po prostu utrzymuje kod czysty, ale można także znaleźć przydatne dla wydajności jeśli często konieczności pobierania <person> elementów opartych na ich <login_name> dziecka.

Musiałbym szablon, który zwrócił sformatowaną nazwę danego <person>:

<xsl:template match="person" mode="name"> 
    <xsl:value-of select="concat(first, ' ', last)" /> 
</xsl:template> 

I wtedy zrobiłbym:

<xsl:template match="current/login_name"> 
    <xsl:apply-templates select="key('people', .)" mode="name" /> 
</xsl:template> 
+0

Dobra, zignoruj ​​moją odpowiedź dalej, ta jest świetna.Czyste i wykonane z ładnych części wielokrotnego użytku. –

+0

Uwielbiam to! dzięki ... nigdy nie słyszałem o xsl: key before ... –

0

myślę co on właściwie chciał zajął w meczu o „aktualnym” węzła, a nie mecz w węźle osobę:

<xsl:variable name="login" select="//current/login_name/text()"/> 

<xsl:template match="current/login_name"> 
<xsl:value-of select='concat(../../people/person[login_name=$login]/first," ", ../../people/person[login_name=$login]/last)'/> 

</xsl:template> 
4

chcesz current() funkcja

<xsl:template match="current/login_name"> 
    <xsl:value-of select="../../people/person[login_name = current()]/first"/> 
    <xsl:text> </xsl:text> 
    <xsl:value-of select="../../people/person[login_name = current()]/last"/> 
</xsl:template> 

lub nieco bardziej czystsze:

<xsl:template match="current/login_name"> 
    <xsl:for-each select="../../people/person[login_name = current()]"> 
    <xsl:value-of select="first"/> 
    <xsl:text> </xsl:text> 
    <xsl:value-of select="last"/> 
    </xsl:for-each> 
</xsl:template> 
+0

thx za bieżący nawet końcówki ... jeśli naprawdę nie lubię używania for-each w xslt ... –

0

Wystarczy dodać moje myśli do stosu

<xsl:template match="login_name[parent::current]"> 
<xsl:variable name="login" select="text()"/> 
<xsl:value-of select='concat(ancestor::people/child::person[login_name=$login]/child::first/text()," ",ancestor::people/child::person[login_name=$login]/child::last/text())'/> 
</xsl:template> 

zawsze wolą używać osie wyraźnie w moim XPath, bardziej gadatliwy ale jaśniejsze IMHO.

W zależności od tego, jak wyglądają pozostałe dokumenty XML (zakładając, że jest to tylko fragment), może być konieczne ograniczenie odwołania do "przodek :: ludzie", na przykład przy użyciu "przodek :: ludzie [1]", aby ograniczyć pierwszemu przodkowi ludzi.

1

Jeżeli chcesz mieć dostęp do wielu użytkowników, a następnie JeniT's <xsl:key /> approach jest idealny.

Oto moja alternatywa wziąć od niego:

<xsl:template match="current/login_name"> 
    <xsl:variable name="person" select="//people/person[login_name = .]" /> 
    <xsl:value-of select="concat($person/first, ' ', $person/last)" /> 
</xsl:template> 

Przypisujemy wybranego węzła <person> do zmiennej, a następnie używamy funkcji concat() do wyjścia pierwsze/ostatnie nazwiska.

Występuje również błąd w przykładowym kodzie XML. Węzeł <person> nieprawidłowo kończy </preson> (typo)

Lepszym rozwiązaniem może być podana gdybyśmy wiedzieli ogólną strukturę dokumentu XML (z węzłów korzeniowych, etc.)

+0

dzięki za napiwek ... działa świetnie ... nie wiem dlaczego, po prostu nie lubię używać zmiennych w xslt ... –

Powiązane problemy