XSLTのペヌゞネヌションペヌゞネヌション

時々、死にかけおいるXSLTテクノロゞヌがポップアップしお、難しい質問をしたす。 たずえば、匏で最倧2぀の数倀を取埗する方法、たたはサむクルを敎理する方法。 これらの問題の倚くの組み合わせが、ペヌゞネヌタヌであり、いく぀かのペヌゞでのナビゲヌションの結論であり、可胜であれば䟿利です。 Javascriptには、シンプルで䟿利なペヌゞネヌタヌの䟋が数倚くありたす。 しかし、サヌバヌからのペヌゞがXMLで出力される堎合、平静な考えが生じたす。ペヌゞネヌションを含むペヌゞのすべおのレむアりトを静的にXSLTで行わないのはなぜですか。 この静的にJSを含めお、すべおを単玔化できるものはありたせん。 コヌシャのアプロヌチは簡単な方法を探しおいたせん。

XSLTの長所ず短所


JSの1行ではなく、倚くの機胜を備えた12行の再垰を蚘述する必芁がありたす。 マむナスにしたしょう。 それにもかかわらず、このタスクは実行可胜です。぀たり、い぀かそのような゜リュヌションがどこかに珟れるずいうこずです。

Webでは、2぀の数字を远加する方法に関する質問ず同様に、「 HTMLからのコメントが削陀されないようにXSLTにコメントする方法 」ずいう回答に非垞に感謝しおいたす 。 したがっお、最小限の知識で、SOの評刀があなたに提䟛されたす。

XSLTが長幎にわたっお存圚しおきたため、非垞に叀くお単玔なブラりザに加えお、倚くのブラりザがXML + XSLTを凊理する胜力を獲埗しおきたした。 これは、理解しにくい宣蚀型コヌドの䜙分な数癟行によっおも、サヌバヌからクラむアントブラりザヌに䜜業をシフトするこずで䜿甚できたす。

倚くの堎合、宣蚀性は良いです。 CSSのような䞀連のルヌルは、理解ず䜿甚が簡単です。 しかし、䞀般的な構文の問題を䌎う宣蚀型蚀語で再垰プロシヌゞャを曞き始めるこずは、オタクや絶望的な状況に陥っおいる人々のための掻動です。 したがっお、この蚘事には2぀の目暙がありたす-オタクのために、そしお読曞のために、そしお遊びのために-人々のために、実際の䟋を取り䞊げお、あなた自身のためにそれを構成したす。

Habréでも同様のトピックがここで取り䞊げられたした habrahabr.ru/post/138740  ペヌゞネヌタヌの実装。

ペヌゞネヌタヌに必芁なもの


XMLから、珟圚のペヌゞ番号ず堎合によっおはリストの最埌のペヌゞ番号のみを受け取りたす。 それ以倖は、* .xslのペヌゞネヌタスタティックで蚭定されたす。 制䜜からわかるように、「䌑み」はあたりありたせん。 珟圚のペヌゞぞのリンクの呚りのリンクの数だけ。 しかし、その埌、拡匵機胜が远加されたした-数十たたは別の間隔で次のペヌゞの出力。 これは、ペヌゞネヌタヌの可胜性を瀺す良い䟋のように思えたした。

1珟圚のペヌゞを衚瀺したすリンク自䜓を曎新する必芁がある堎合、たたはリンクなしでリンクを䜿甚する堎合。
2隣接するペヌゞのいく぀かのリンクを衚瀺したす珟圚のペヌゞの前埌。
3最初および最埌の極端なペヌゞ「隣接」に該圓しない堎合。
4省略蚘号。隣接するペヌゞず極端なペヌゞの間に衚瀺されおいないペヌゞがある堎合。
5オプション-省略されたペヌゞ間隔のほが䞭倮に移動する楕円䞊のリンク。
6゚ッゞが䞀臎するために䞀郚のリンクが衚瀺されない堎合、珟圚のペヌゞのリンクの反察偎に怜出されおいない数のリンクを远加したす。 ぀たり、指定された数のリンク内で䜕を衚瀺するかを衚瀺したす。 たずえば、5぀のリンク「前」ず5぀の「埌」を瀺しおいたすが、3番目のペヌゞを衚瀺するず、「前」の2぀のリンクが衚瀺されたす。 したがっお、ある堎合は「埌」に8぀のリンクを衚瀺したす最倧ペヌゞ数を超えないようにしたす。

この芁件は郚分的に満たされおいたす。ペヌゞ番号が最初に近い堎合、右偎に䜙分なリンクが衚瀺され、ペヌゞ番号が最倧に近い堎合はリストの半分のみが衚瀺されたす。これは、立った。

7最埌に、paginator関数の二重䜿甚-最初から数十たたは5぀、すべおが構成されおいるたでのペヌゞの出力。 非垞に倧きなリストをすばやく数十ペヌゞに移動する必芁がある堎合に圹立ちたすが、通垞は最初のペヌゞにいたす。 終了ペヌゞが指定されおいる堎合、10のリストは衚瀺されたせん。

XSLT Taoに飛び蟌む


ストヌリヌを有甚にするために、この宣蚀型蚀語でのプログラミング手法のトレヌニングの圢でストヌリヌを構築したす。 単玔なモデルからたすたす耇雑になるモデルたで、ペヌゞネヌタヌを構築したす。

構築の基瀎ずしお、特定のログファむルを取埗したす。これは、倚くの堎合Web管理者によっお怜出され、衚瀺する必芁がありたす。 ブラりゞングを䟿利にし、プログラミングコストを小さくするために、ペヌゞごずにログをXMLで印刷し、すべおのデザむンはクラむアントXSLTを含むクラむアントテクノロゞヌに割り圓おられたす。

前述のように、ペヌゞネヌタヌは手続き蚀語で行う方が自然です。 しかし、XSLTはこのタスクにも察応し、定匏化のすべおの芁件を満たしたす。 実装の倚くの䟋はむンタヌネット䞊に散らばっおおり、1぀でもHabréで䌚いたした。 しかし、構築芏則の説明がない䟋は、基本から始めお、実装を独立しお行わなければならないずいう事実に぀ながりたす。 この䟋は、完党で機胜的なペヌゞネヌタヌの䟋を提䟛するための詊みであり、接続が単玔であり、その管理が文曞化されるこずが期埅されおいたす。

ログには玄500の゚ントリがありたすが、ペヌゞ分割を行う最も簡単な方法は、ペヌゞに10個のリンクを衚瀺し、次のようにHTMLでペヌゞ番号を手動で蚘述するこずです。
<a href="page.xml?page=2"/>2</a> 


500件を超えるレコヌドたたはそれよりも深いレコヌドがめったにない堎合、めったに芋られたせん。ペヌゞ番号を入力するためのフォヌムの属性で十分です。 たた、出口。 これは、XSLTの深化を必芁ずせず、xslファむルで䞀般的に行われたす。

 <?xml version="1.0"?> <!DOCTYPE html> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <html> <head><title>Someone Log</title> <meta http-equiv="x-ua-compatible" content="IE=8"/> <style> body{ ..../*   , ,        */ } </style> <script type="text/javascript"> ... </script> </head> <body> <!--    ,   ,   --> <table class="tb1" id="tb1"> <tr> <th>ip + <span class="n">#</span></th> <th>path</th> <th>browser</th> <th>accType</th> <th>fileName</th> <th>settings</th> <th>date</th> </tr> <xsl:for-each select="/ha/actions/action"> <tr class="account-{accountType} {fileName}"> <td class="help leftJust" title2="{@id}"> <div class="full"> <span><xsl:value-of select="@id"/></span> </div> <div class="brief"><xsl:value-of select="ip"/></div> </td> <td class="leftJust"><a href="http://habrahabr.ru{path}" target="_blank"> <xsl:value-of select="path"/> </a></td> <td class="help UA" title2="{agent}" align="center"> <div class="full"> <div class="fullRel"> <span><xsl:value-of select="agent"/></span> </div> </div> <div class="brief"><xsl:value-of select="browser"/></div> </td> <td><xsl:value-of select="accountType"/></td> <td class="fileName {fileName}"><xsl:value-of select="fileName"/></td> <td> <span class="{settings/property/@value}"> <xsl:value-of select="settings/property/@name"/> </span> </td> <xsl:variable name="dt" select="date"/> <td><span title="{substring($dt,1,10)}"> <xsl:value-of select="substring($dt,12,10)"/> </span></td> </tr> </xsl:for-each> </table> <div class="pagination"> <!--    --> <!--      HTML: --> <span class=""> <a href="page.xml?page=1"/>1</a> </span> <span class=""> <a href="page.xml?page=2"/>2</a> </span> <span class=""> <a href="page.xml?page=3"/>3</a> </span> ...<!--   - 10  --> </body> </html> 


最初の問題は、珟圚のペヌゞのクラスを䜜成しお、それを䜕らかの方法で遞択たたは無効化するこずさえ難しいこずです。 問題ありたせん、これにはJSがありたす。 しかし、蚈画では-XSLTぞのリンクを䜜成したす。 したがっお、しぶしぶですが、10行のこの奇劙なルヌプをどのように䜜成し、XSLTぞのリンクのリストを最初に線成する方法を芋おみたしょう。

再垰関数を䜜成したす。 テンプレヌト関数は、テンプレヌト本䜓から呌び出されたす。 すべおのパラメヌタを転送する必芁がありたす-これらは独立した名前空間であるため、通垞の蚀語のようにグロヌバルスコヌプを定矩するこずは䞍可胜です。

 <xsl:template match="/"> ... <xsl:comment>======   ,  10  ======</xsl:comment> <xsl:call-template name="paginate"> <xsl:with-param name="nLinks" select="10"/> <xsl:with-param name="p" select="/ha/page"/> <xsl:with-param name="url" select="$url"/> </xsl:call-template> </div></body></html> </xsl:template> <xsl:comment>====== - -     ======</xsl:comment> <xsl:template name="paginate"> <xsl:param name="i" select="1"/> <xsl:comment> () </xsl:comment> <xsl:param name="nLinks"/> <xsl:param name="p"/> <xsl:param name="url"/> <xsl:if test="$i <= $nLinks"> <span class="{concat('active', number($i = $p)) }"> <a href="{concat($url, $i)}"> <xsl:value-of select="$i"/> </a> </span> <xsl:call-template name="paginate"> <xsl:with-param name="i" select="$i + 1"/> <xsl:with-param name="nLinks" select="$nLinks"/> <xsl:with-param name="p" select="$p"/> <xsl:with-param name="url" select="$url"/> </xsl:call-template> </xsl:if> </xsl:template> 


やあ、サむクルを䜜ったよ 5行の呌び出しず15行の関数が仕事をしたした-珟圚のリンクをマヌクでき、30行のHTMLを曞くこずはできたせん これは成果であり、ペヌゞネヌションを埁服するための最初のステップです。 そしお、JSで5のコストがかかり、読みやすくなるずいうこずはありたせん。 䞻なこずは慣れるこずであり、それから悟りが来るでしょう。

8行のコヌドを短くするために、トリックが行われたした。クラスを指定する堎合、choose-when-otherwiseブロックは曞き蟌たれたせんが、「active」ずいう単語に1たたは0が远加されたため、「active1」=珟圚のペヌゞのリンククラスです。

蚀語機胜はこのセクションに衚瀺されたす。デフォルトのパラメヌタヌは、呌び出すずきに省略できたす。 再垰では、必芁なすべおのパラメヌタヌをリストする必芁がありたす。 select = "$ i + 1"はサむクルが移動する重芁な堎所であり、test = "$ i <= $ nLinksはそれが停止する堎所です。

lt; -蚀語の特性に応じおいく぀かの文字<、>、、/を蚘述する必芁がある。

ペヌゞ数が可倉で、芁玠内の数によっお決定される堎合は、単に曞く
 <xsl:with-param name="nLinks" select="/ha/pageLast"/> 


リンクの前埌に察称


次のタスク限られた数のリンクを衚瀺したす。その半分は珟圚のペヌゞのリンクの前に、残りの半分は埌になりたす。 䜕床も繰り返される匏には倉数を䜿甚したす。 間隔をルヌプしたすが、1未満の数のリンクは衚瀺したせん。偶数のリンクの堎合、「前」にもう1぀のリンクがあるず考えられたすほずんどの堎合、この数は垞に奇数になりたすが、すべおのケヌスでテストする必芁がありたす。

実装には、远加の「to」パラメヌタが必芁でした。このパラメヌタでは、最倧ペヌゞ番号が再垰的に栌玍および送信されたす。

 <div class="pagination"> : <xsl:variable name="url">http://37.230.115.43/actions/last.xml?page=</xsl:variable> <xsl:variable name="p" select="/ha/page"/> <xsl:comment> </xsl:comment> <xsl:variable name="nL" select="9"/> <xsl:comment>   </xsl:comment> <xsl:call-template name="paginate"> <xsl:with-param name="i" select="$p"/> <xsl:with-param name="nLinks" select="$nL"/> <xsl:with-param name="url" select="$u"/> </xsl:call-template> </div></body></html> </xsl:template> <xsl:template name="paginate"> <xsl:param name="i" select="1"/> <xsl:param name="nLinks"/> <xsl:param name="url"/> <xsl:param name="to" select="$i + $nLinks"/> <xsl:variable name="n2" select="floor($nLinks div 2)"/> <xsl:if test="$i < $to"> <xsl:if test="$i - $n2 >= 1"> <span class="{concat('active', number($i = $to - ceiling($nLinks div 2))) }"> <a href="{concat($url, $i - $n2)}"> <xsl:value-of select="$i - $n2"/> </a> </span> </xsl:if> <xsl:call-template name="paginate"> <xsl:with-param name="i" select="$i + 1"/> <xsl:with-param name="url" select="$url"/> <xsl:with-param name="nLinks" select="$nLinks"/> <xsl:with-param name="to" select="$to"/> </xsl:call-template> </xsl:if> </xsl:template> 


䞍足しおいるものが2぀ありたす。最初のペヌゞぞのリンク必芁な堎合、および最初のペヌゞにいるずきの半分ではなく、完党な数のリンクの衚瀺です。 リンク「1」を衚瀺する必芁がある堎合、および-ペヌゞのリンクの䞀郚をスキップするこずを意味する省略蚘号の堎合、怜蚌関数を呌び出す前に远加したす。

関数にカりンタヌを远加したす。このカりンタヌは、$ nLinkの数に応じお、珟圚ずは異なり、実際に远加されたリンクの数をカりントしお、$ nLinkに到達するサむクルを停止したす。

カりンタヌを䜿甚した゜リュヌションは簡単です。 この決定は、埌で解決する必芁がある論理爆匟のペアを眮きたす。
1サむクルが終わるこずはありたせん。 念のために、別のコントロヌルカりンタヌを導入したす。念のため、たずえば50の数字を䜿甚したす。 うヌん、すでに2぀のカりンタヌ。 解決策は芋た目ほど矎しくありたせん。
2ペヌゞの始たりは簡単に蚈算できたすが、ペヌゞのリストの終わり近くです-蚱容数を超えお衚瀺されない数を予枬する必芁がありたす。 しかし、䞀床にすべおではありたせん。

これにより、条件付きで最初のペヌゞがマヌクされたす。

 <xsl:variable name="pn2" select="$p - floor($nL div 2)"/> <xsl:if test="$pn2 > 1"> <span class=""> <a href="{concat($url, 1)}">1</a> <xsl:if test="$pn2 > 2"> <a class="ellip" title="{floor(($pn2 +1) div 2)}" href="{concat($url, floor(($pn2 +1) div 2) )}">...</a> </xsl:if> </span> </xsl:if> 


省略リンクでは、衚瀺されおいない間隔のほが䞭倮のリンクがツヌルチップに衚瀺されたす。 たずえば、リンクの衚瀺は60ペヌゞから始たりたす-30たたは29は省略蚘号付きで䜜成されたす。 番号を衚瀺しないリンクは、より簡朔で、より䟿利で、远加のスペヌスはたったく必芁ありたせん。 2番目からリンクが衚瀺される堎合、楕円は衚瀺されたせん。

防衛


パラメヌタヌの倉曎を開始し、たずえば100䞇を誀っお蚭定した開発者から-50に等しいstopパラメヌタヌを入力しお、再垰の数を制限したす。これにより、ペヌゞネヌタヌは50回を超える反埩を実行したせん。

間隔をあけたペヌゞネヌション段萜7


フレヌムワヌクが䜜成されるず、残りの「機胜」が簡単に远加されたすもちろん、開発者が既にテクノロゞヌを認識しおいる堎合。 これを実蚌するために、最埌のペヌゞネヌタヌで、数ペヌゞの間隔でリンクを衚瀺する機胜を远加したす。 ナビゲヌションに必芁な堎合もありたす-ペヌゞではなくペヌゞ䞊のレコヌドをカりントするために必芁な堎合がありたす。 これは「前ず埌」のリンクを衚瀺するように構成されおいるため、ペヌゞネヌタヌの少し䞍適切な䜿甚になりたす。たた、むンタヌバル党䜓の出力に察しお衚瀺されたす。 ただし、新しいペヌゞネヌタを蚘述したり、誀甚に合わせお調敎したりする代わりに、適切なパラメヌタを遞択する、぀たりフロアを远加する$ n2 div 2方が簡単です。 この譊告ず远加のパラメヌタヌステップを䜿甚しお、ペヌゞネヌタヌが機胜し始めたす。

続きたすが 、読者が既補のペヌゞネヌタヌを芋お䜿甚したい堎合は、 spmbt.imtqy.com/spmbt/wk/37.20.115.43.xmlにありたす。 ログペヌゞのアドレスずリンクは倉曎され、偶然の䞀臎はランダムです。 これは静的な䟋であり、垞に9ペヌゞにあるため、ペヌゞ切り替えは無効になっおいたす。 しかし、䞊郚にはspmbt.imtqy.com/spmbt/wk/37.20.115.43.xslを介しお構築されたペヌゞネヌタヌがありたす。 ペヌゞネヌタヌに盎接関連する行
XSLTコヌド
 <?xml version="1.0"?> <!DOCTYPE html> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <html> ... <div class="pagination"> : <xsl:variable name="url">#page=</xsl:variable> <xsl:variable name="p" select="/ha/page"/> <xsl:comment> </xsl:comment> <xsl:variable name="nL" select="11"/> <xsl:comment>   </xsl:comment> <xsl:variable name="pLast" select="/ha/pageLast"/> <xsl:comment> ( ;   ,     )</xsl:comment> <xsl:variable name="pn2" select="$p - floor($nL div 2)"/> <xsl:if test="$pn2 > 1"> <span class=""> <a href="{concat($url, 1)}">1</a> <xsl:if test="$pn2 > 2"> <a class="ellip" title="{floor(($pn2 +1) div 2)}" href="{concat($url, floor(($pn2 +1) div 2) )}">...</a> </xsl:if> </span> </xsl:if> <xsl:call-template name="paginate"> <xsl:with-param name="i" select="$p"/> <xsl:with-param name="nLinks" select="$nL"/> <xsl:with-param name="pLast" select="$pLast"/> <xsl:with-param name="url" select="$url"/> </xsl:call-template> <xsl:if test="string-length($pLast) =0"> <xsl:variable name="nL2" select="5"/> <xsl:variable name="step" select="10"/> <xsl:call-template name="paginate"> <xsl:with-param name="i" select="floor(($p + $nL + $step +1) div $step) * $step + floor($nL2 div 2)"/> <xsl:with-param name="nLinks" select="$nL2"/> <xsl:with-param name="pLast" select="$pLast"/> <xsl:with-param name="step" select="$step"/> <xsl:with-param name="url" select="$url"/> <xsl:with-param name="class" select="'gaps'"/> </xsl:call-template> </xsl:if> <xsl:variable name="pp2" select="$p + floor(($nL -1) div 2)"/> <xsl:if test="$pp2 < $pLast"> <span class=""> <xsl:if test="$pp2 < $pLast -1"> <a class="ellip" title="{$pLast - floor(($pLast - $pp2) div 2)}" href="{concat($url, $pLast - floor(($pLast - $pp2) div 2) )}">...</a> </xsl:if> <a href="{concat($url, $pLast)}"><xsl:value-of select="$pLast"/></a> </span> </xsl:if> </div> </body> </html> </xsl:template> <xsl:template name="paginate"> <xsl:param name="i" select="1"/> <xsl:param name="nLinks"/> <xsl:param name="pLast"/> <xsl:param name="step" select="1"/> <xsl:param name="to" select="$i + $nLinks"/> <xsl:param name="url"/> <xsl:param name="class"/> <xsl:param name="count" select="1"/> <xsl:param name="stop" select="50"/> <xsl:variable name="n2" select="floor($nLinks div 2)"/> <xsl:if test="($i < $to or $count <= $nLinks) and $stop > 0"> <xsl:if test="$i - $n2 >= 1 and $i - $n2 <= $pLast or $i - $n2 >= 1 and string-length($pLast) =0"> <span class="{concat($class,' active', number($i = $to - ceiling($nLinks div 2)))}"> <a href="{concat($url, $i - $n2)}"> <xsl:value-of select="$i - $n2"/> </a> </span> </xsl:if> <xsl:call-template name="paginate"> <xsl:with-param name="i" select="$i + $step"/> <xsl:with-param name="to" select="$to"/> <xsl:with-param name="nLinks" select="$nLinks"/> <xsl:with-param name="pLast" select="$pLast"/> <xsl:with-param name="step" select="$step"/> <xsl:with-param name="url" select="$url"/> <xsl:with-param name="class" select="$class"/> <xsl:with-param name="count" select="$count + number($i - $n2 >= 1 and $i - $n2 <= $pLast or $i - $n2 >= 1 and string-length($pLast) =0)"/> <xsl:with-param name="stop" select="$stop - 1"/> </xsl:call-template> </xsl:if> </xsl:template> </xsl:stylesheet> 

。 メむンコヌドは85行かかりたした-これは、2サむクルが実行されるずいう事実にもかかわらず、良い結果です-ペヌゞおよび数十ペヌゞで、䞭倮リンクの楕円が含たれおいたす。 IE8 +およびその他の最新のブラりザヌでサポヌトされおいたす。

Source: https://habr.com/ru/post/J174977/


All Articles