2009-09-07 15 views
7

Mam pytanie dotyczące sortowania funkcji losowych w XSLT.Losowo wybierz węzeł w XSLT

Mam pliku XML, że bardzo uproszczone wyglądać podobnie do tego:

<node id="1198"> 
    <node id="1201"> 
    <data alias="name">Flemming</data> 
    <data alias="picture">1200</data> 
    </node> 
    <node id="1207"> 
    <data alias="name">John</data> 
    <data alias="picture">1205</data> 
    </node> 
    <node id="1208"> 
    <data alias="name">Michael</data> 
    <data alias="picture">1206</data> 
    </node> 
</node> 

chciałbym mieć jakiś XSLT, że ramdomly wziął jeden z węzłów identyfikatory i umieścić ją w zmiennej o nazwie „choosenNode ". Podoba Ci się to, jeśli węzeł z identyfikatorem 1207 został wybrany jednym:

<xsl:variable name="choosenNode" value="1207" /> 

Jak mogę to zrobić? Czy istnieje funkcja losowa w XSLT? Przy okazji, chciałbym, aby zmienna była odświeżana na każdej stronie, na której znajduje się XSLT.

Pracuję w systemie CMS Umbraco, jeśli to ci pomoże.

Dzięki, -Kim

Odpowiedz

7

W Umbraco można zrobić coś takiego:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE xsl:Stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]> 
<xsl:stylesheet 
version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:msxml="urn:schemas-microsoft-com:xslt" 
xmlns:umbraco.library="urn:umbraco.library" 
xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" 
exclude-result-prefixes="msxml umbraco.library Exslt.ExsltMath"> 

<xsl:output method="xml" omit-xml-declaration="yes"/> 

<xsl:param name="currentPage"/> 

<!-- This should probably be a macro parameter so you can use this elsewhere--> 
<xsl:variable name="parentNode" select="1048"/> 

<xsl:template match="/"> 

     <xsl:variable name="numberOfNodes" select="count(umbraco.library:GetXmlNodeById($parentNode)/node)"/> 

     <xsl:variable name="randomPosition" select="floor(Exslt.ExsltMath:random() * $numberOfNodes) + 1"/> 

     <xsl:variable name="randomNode" select="umbraco.library:GetXmlNodeById($parentNode)/node [position() = $randomPosition]"/> 

     <!-- 
      You now have the node in the $randomNode variable 
      If you just want the id then you can do an XPath query on the variable 
      or you can modify the XPath above to get the property you are after rather than 
      the whole node 
     --> 

    <xsl:value-of select="$randomNode/@nodeName" /> 

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

nadzieję, że to pomaga.

Tim

+0

To wygląda całkiem fajnie Tim, to może być dobre rozwiązanie. Sprawdzę to jutro, więc dostaniesz poprawną odpowiedź, jeśli zadziała: D Dzięki ... –

+0

OK - Właściwie to nie sprawdziłem kodu - po prostu wpisałem go z góry mojej głowy , więc strzeż się błędów! –

+0

OOOPS - tam kilka małych literówek. Uporządkowałem to i sprawdziłem, czy działa w jednej z moich instalacji Umbraco. Dodałem także wiersz pokazujący, jak pobrać wartość. –

0

Getting liczbę losową w XSLT nie jest łatwym zadaniem.

Jest coś, co można zrobić, ale prawdopodobnie ma dostarczyć ziarno dla generatora http://fxsl.sourceforge.net/articles/Random/Casting%20the%20Dice%20with%20FXSL-htm.htm

Może procesora używanego zrobić transformacji xsl ma zdolność do rozszerzenia wyrażeń XSL z funkcji zewnętrznych. W takim przypadku możesz użyć zewnętrznej funkcji.

+0

Umbraco ma dostęp do własnej biblioteki funkcji rozszerzających i tych Microsoft wewnątrz procesora XSLT, tak ten problem został rozwiązany. Chociaż skryptowanie wewnątrz procesora XSLT może uderzać w serwer –

0

Wszystko czego potrzebujesz to generator liczb losowych. Nie ma żadnego w XSLT, więc losowa liczba musi być dostarczona przez coś poza XSLT. Będziesz musiał wywołać metodę z zewnętrznej biblioteki, aby to zrobić, a implementacja tej biblioteki będzie zależeć od tego, czy jesteś w systemie Windows (.NET lub WIN32) lub Linux i procesorze XSLT. XSLT potrafi wykonywać matematykę, ale brakuje w niej wielu funkcji związanych z datą/czasem, które obejmują generator liczb losowych.

Jednak XSLT ma funkcję XPath o nazwie generate-id(), która wygeneruje unikalny identyfikator. Jeśli mógłbyś jakoś przekształcić to w nuimber, może on zostać użyty do stworzenia losowej liczby, chociaż byłby przewidywalny, a niektóre liczby mogłyby występować częściej niż inne. Nie użyłbym tego.

Jeśli używasz MSXSL do przetworzenia arkusza stylów, możesz dołączyć JavaScript w celu wygenerowania liczb losowych w arkuszu stylów. (Lub skrypt C# podczas korzystania z .NET.)

Uzyskanie samego węzła jest łatwe, gdy znasz liczbę węzłów potomnych. Po prostu poproś o węzeł w losowej pozycji. Coś jak/node/node [5] zwróci 5 węzeł.

0

To rozwiązanie działa skrypt powłoki, który używa xsltproc i tekstowych narzędzi.

RandomElement=$(xsltproc style.xsl file.xml | tr ' ' '\n' | sort -uR | head -n 1) 

To zakłada, że ​​plik style.xsl będzie wybrać żądany zestaw elementów i powrócić to wartości, po jednej linii w pliku tekstowym wyjście. Polecenie tr powinno umieścić każdy element na osobnej linii. Model sort -uR powinien tworzyć unikatową, losową listę elementów wybranych za pomocą poleceń arkusza stylów z zakresu style.xsl. head -n 1 następnie wyciąga pierwszą linię z unikatowej, losowej listy.

0

Następujący zakłada, że ​​procesor XSLT obsługuje rozszerzenia EXSLT (np. Xsltproc).

Spowoduje to zwrócenie zawartości losowo wybranego "węzła" (musi to być element potomny "węzła", tj. Element "węzeł/węzeł").

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:math="http://exslt.org/math" 
    extension-element-prefixes="math" > 

<xsl:template match="/"> 
    <xsl:apply-templates/> 
</xsl:template> 

<xsl:template match="node"> 
    <xsl:variable name='selected'> 
    <xsl:value-of select="ceiling(math:random() * count(node))"/> 
    </xsl:variable> 
    <xsl:copy-of select="node[position() = $selected]"/> 
</xsl:template> 
</xsl:stylesheet> 

Może to być przydatne, fragment do przetwarzania zawartości wybranego węzła:

<xsl:variable name="randomNode" select="node[position() = $selectNode]"/> 
<id><xsl:value-of select="$randomNode/@id"/></id> 
<name><xsl:value-of select="$randomNode/data[@alias='name']"/></name> 
<picture><xsl:value-of select="$randomNode/data[@alias='picture']"/></picture> 

Należy zauważyć, że wyżej nie zwraca definicji XSLT zmiennej, używa zmienna, aby skopiować wybrany węzeł.

Aby ustawić „wartość” atrybutu xsl: variable elementu, spróbuj szablon atrybutów takich jak:

<xsl:variable name='chosenNode' value='{node[position() = $selected]/@id}'/> 
Powiązane problemy