How to organize XML records

XML:

<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template name="displaySpecNav" match="/"> <xsl:for-each select="/root"> <div class="hidOverflow vertAlignT setCenter smallPadBottom"> <div id="dvExpProvHolder" class="hidOverflow innerDivCenter"> <ul class="uSPStyle" id="uSPStyle"> <!-- <xsl:sort select="mOrder" /> --> <li class="setRelative"> <a class="tfLink clickMe current" title="{grp1/tfLink01}" data-toggle=".tfLink1" href="javascript:void(0);"> <xsl:value-of select="grp1/tfLink01" /> </a> </li> <li> <a class="tfLink clickMe" title="{grp2/tfLink02}" data-toggle=".tfLink2" href="javascript:void(0);"> <xsl:value-of select="grp2/tfLink02" /> </a> </li> <li> <a class="tfLink clickMe" title="{grp3/tfLink03}" data-toggle=".tfLink3" href="javascript:void(0);"> <xsl:value-of select="grp3/tfLink03" /> </a> </li> </ul> </div> </div> </xsl:for-each> </xsl:template> </xsl:stylesheet> 

XSLT:

 <?xml version="1.0" encoding="UTF-8"?> <root> <grp1> <tfLink01>Link #2</tfLink01> <mOrder>2</mOrder> <tfText01 /> <cfSM1>false</cfSM1> <tf1SLink01 /> <tf1SText01 /> <tf2SLink01 /> <tf2SText01 /> <tf3SLink01 /> <tf3SText01 /> </grp1> <grp2> <tfLink02>Link #1</tfLink02> <mOrder>1</mOrder> <tfText02 /> <cfSM2>false</cfSM2> <tf1SLink02 /> <tf1SText02 /> <tf2SLink02 /> <tf2SText02 /> <tf3SLink02 /> <tf3SText02 /> </grp2> <grp3> <tfLink03>Link #3</tfLink03> <mOrder>3</mOrder> <tfText03 /> <cfSM3>false</cfSM3> <tf1SLink03 /> <tf1SText03 /> <tf2SLink03 /> <tf2SText03 /> <tf3SLink03 /> <tf3SText03 /> </grp3> </root> 

The abode XML / XSLT architecture displays the following unordered list:

 Link #2 Link #1 Link #3 

How can I change XSLT, so <xsl:sort select="mOrder" /> works correctly and displays the following:

 Link #1 (although this is the second entry) Link #2 (although this is the first entry) Link #3 

In addition, grp1 , grp2 and grp3 were added in this example, so I can add the mOrder selection several times, which if I don't have a group and have the following XML (my current setup and would like to save it that way):

 <?xml version="1.0" encoding="UTF-8"?> <root> <tfLink01>Link #2</tfLink01> <mOrder1>2</mOrder1> <tfText01 /> <cfSM1>false</cfSM1> <tf1SLink01 /> <tf1SText01 /> <tf2SLink01 /> <tf2SText01 /> <tf3SLink01 /> <tf3SText01 /> <tfLink02>Link #1</tfLink02> <mOrder2>1</mOrder2> <tfText02 /> <cfSM2>false</cfSM2> <tf1SLink02 /> <tf1SText02 /> <tf2SLink02 /> <tf2SText02 /> <tf3SLink02 /> <tf3SText02 /> <tfLink03>Link #3</tfLink03> <mOrder3>3</mOrder3> <tfText03 /> <cfSM3>false</cfSM3> <tf1SLink03 /> <tf1SText03 /> <tf2SLink03 /> <tf2SText03 /> <tf3SLink03 /> <tf3SText03 /> </root> 

How can I handle the XML format.

0
source share
2 answers

Better if you structure your XML as follows (unused fields are omitted for brevity):

 <?xml version="1.0" encoding="UTF-8"?> <root> <grp> <tfLink>Link #2</tfLink> <mOrder>2</mOrder> </grp> <grp> <tfLink>Link #1</tfLink> <mOrder>1</mOrder> </grp> <grp> <tfLink>Link #3</tfLink> <mOrder>3</mOrder> </grp> </root> 

Then your XSLT will become:

 <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/root"> <div class="hidOverflow vertAlignT setCenter smallPadBottom"> <div id="dvExpProvHolder" class="hidOverflow innerDivCenter"> <ul class="uSPStyle" id="uSPStyle"> <xsl:for-each select="grp"> <xsl:sort select="mOrder" /> <li> <a class="tfLink clickMe" title="{tfLink}" href="javascript:void(0);" data-toggle='collapse' data-target="#{generate-id()}"> <xsl:value-of select="tfLink" /> </a> </li> </xsl:for-each> </ul> </div> </div> </xsl:template> </xsl:stylesheet> 

I also changed data-toggle (I assume it is Bootstrap) to name the class it should switch ( collapse as an example), and data-target use generate-id() , which you should use when generating content, which will act.

The XML derived from the above is as follows:

 <?xml version="1.0"?> <div class="hidOverflow vertAlignT setCenter smallPadBottom"> <div id="dvExpProvHolder" class="hidOverflow innerDivCenter"> <ul class="uSPStyle" id="uSPStyle"> <li> <a class="tfLink clickMe" title="Link #1" data-toggle="collapse" data-target="#idp31396560" href="javascript:void(0);">Link #1</a> </li> <li> <a class="tfLink clickMe" title="Link #2" data-toggle="collapse" data-target="#idp31377232" href="javascript:void(0);">Link #2</a> </li> <li> <a class="tfLink clickMe" title="Link #3" data-toggle="collapse" data-target="#idp31398000" href="javascript:void(0);">Link #3</a> </li> </ul> </div> </div> 

If you need to set attributes for the first element in xsl: for-each, you can use it in XSLT:

 <xsl:for-each ...> <xsl:sort .../> <li> <xsl:if test="position()=1"> <xsl:attribute name="class">setCurrent</xsl:attribute> </xsl:if> 

and similar for <a> .

+1
source

Given the following input:

XML

 <root> <tfLink01>Link #2</tfLink01> <mOrder>2</mOrder> <tfText01 /> <cfSM1>false</cfSM1> <tf1SLink01 /> <tf1SText01 /> <tf2SLink01 /> <tf2SText01 /> <tf3SLink01 /> <tf3SText01 /> <tfLink02>Link #1</tfLink02> <mOrder>1</mOrder> <tfText02 /> <cfSM2>false</cfSM2> <tf1SLink02 /> <tf1SText02 /> <tf2SLink02 /> <tf2SText02 /> <tf3SLink02 /> <tf3SText02 /> <tfLink03>Link #3</tfLink03> <mOrder>3</mOrder> <tfText03 /> <cfSM3>false</cfSM3> <tf1SLink03 /> <tf1SText03 /> <tf2SLink03 /> <tf2SText03 /> <tf3SLink03 /> <tf3SText03 /> </root> 

following style:

XSLT 1.0

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/> <xsl:template match="/root"> <ul> <xsl:for-each select="mOrder"> <xsl:sort/> <li> <xsl:value-of select="preceding-sibling::*[1]"/> </li> </xsl:for-each> </ul> </xsl:template> </xsl:stylesheet> 

will return:

 <ul> <li>Link #1</li> <li>Link #2</li> <li>Link #3</li> </ul> 

Note :

You can write the serial number in a variable, for example:

 <xsl:variable name="ordinal" select="substring-after(name(preceding-sibling::*[1]), 'tfLink')" /> 

and use it to address additional nodes by their name, and not by their position in the "block".


Added:

For input, where the mOrder nodes mOrder also numbered, that is:

XML

 <root> <tfLink01>Link #2</tfLink01> <mOrder1>2</mOrder1> <tfText01 /> <cfSM1>false</cfSM1> <tf1SLink01 /> <tf1SText01 /> <tf2SLink01 /> <tf2SText01 /> <tf3SLink01 /> <tf3SText01 /> <tfLink02>Link #1</tfLink02> <mOrder2>1</mOrder2> <tfText02 /> <cfSM2>false</cfSM2> <tf1SLink02 /> <tf1SText02 /> <tf2SLink02 /> <tf2SText02 /> <tf3SLink02 /> <tf3SText02 /> <tfLink03>Link #3</tfLink03> <mOrder3>3</mOrder3> <tfText03 /> <cfSM3>false</cfSM3> <tf1SLink03 /> <tf1SText03 /> <tf2SLink03 /> <tf2SText03 /> <tf3SLink03 /> <tf3SText03 /> </root> 

you can use:

 <xsl:template match="/root"> <ul> <xsl:for-each select="*[starts-with(name(), 'tfLink')]"> <xsl:sort select="following-sibling::*[1]"/> <li> <xsl:value-of select="."/> </li> </xsl:for-each> </ul> </xsl:template> 
+1
source

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


All Articles