Home > other >  using XSL to sort elements
using XSL to sort elements

Time:08-07

(This is a follow-up to my previous XSL question, using the same sample data that I posted there. I'm posting the sample data again here, because I got scolded for just posting links the first time.)

Sample-Input.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Entry1</key>
    <dict>
        <key>EntryCollectionA</key>
        <dict>
            <key>ECA Identifier</key>
            <dict>
                <key>ECADetail1</key>
                <string>The quick brown fox</string>
                <key>ECADetail2</key>
                <integer>1112</integer>
            </dict>
        </dict>
        <key>EntryCollectionB</key>
        <dict>
            <key>Identifier for the first ECB</key>
            <dict>
                <key>ECBMinorDetail1</key>
                <false/>
                <key>ECBMinorDetail2</key>
                <dict>
                    <key>EBC2's name</key>
                    <string>jumps over the lazy dog.</string>
                </dict>
                <key>ECBImportantDetail3</key>
                <string>three</string>
                <key>ECBImportantDetail4</key>
                <string>four</string>
                <key>ECBImportantDetail5</key>
                <string>five</string>
                <key>ECBIrrelevantToMe</key>
                <data>
                yadda yadda yadda/yadda yaddayaddayaddayadda
                </data>
                <key>ECBIrrelevantToo</key>
                <integer>987654321</integer>
            </dict>
            <key>second ECB for Entry1 has a different title</key>
            <dict>
                <key>ECBMinorDetail1</key>
                <false/>
                <key>ECBMinorDetail2</key>
                <dict>
                    <key>a name for Ecb2 goes here</key>
                    <string>vaults above the recalcitrant canine.</string>
                </dict>
                <key>ECBImportantDetail3</key>
                <string>is the number of the count,</string>
                <key>ECBImportantDetail4</key>
                <string>and what the number of the count shall be</string>
                <key>ECBImportantDetail5</key>
                <string>is right out.</string>
                <key>ECBIrrelevantToMe</key>
                <data>
                MORE/inde cipher able/and IRReleVaNTinbase64
                </data>
                <key>ECBIrrelevantToo</key>
                <integer>19283746</integer>
            </dict>
            <key>Entry1 third ECB</key>
            <dict>
                <key>ECBMinorDetail1</key>
                <true/>
                <key>ECBMinorDetail2</key>
                <dict>
                    <key>Ecb3 has a name</key>
                    <string>is intimidated by the sleeping dragon.</string>
                </dict>
                <key>ECBImportantDetail3</key>
                <string>is a magic number</string>
                <key>ECBImportantDetail4</key>
                <string>is the legs in a zoo</string>
                <key>ECBImportantDetail5</key>
                <string>ready or not, here I come!</string>
                <key>ECBIrrelevantToMe</key>
                <data>
                WiLlY0USt1lLFe3dMe/WhEnImSiXtYfOuR/60plUsF0R
                </data>
                <key>ECBIrrelevantToo</key>
                <integer>6406406566</integer>
            </dict>
        </dict>
        <key>ImportantDatum6</key>
        <string>what this data pertains to</string>
        <key>ImportantDatum7</key>
        <string>reference code</string>
        <key>ImportantDatum8</key>
        <string>one,two</string>
        <key>whoCares</key>
        <integer>1</integer>
        <key>iDo-aboutThisOne</key>
        <string>999</string>
        <key>ANDagain</key>
        <string>eeny</string>
        <key>moreSillyData</key>
        <data>
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        </data>
        <key>bucketObits</key>
        <string>more characters</string>
        <key>bitObuckets</key>
        <string>textity textext</string>
        <key>amount</key>
        <integer>66645714</integer>
        <key>code</key>
        <integer>765432109</integer>
        <key>subcode</key>
        <integer>828474104</integer>
    </dict>
    <key>second entry</key>
    <dict>
        <key>EntryCollectionA</key>
        <dict>
            <key>5564738291</key>
            <dict>
                <key>wardrobe</key>
                <string>lionWitch</string>
                <key>buuleeun</key>
                <false/>
            </dict>
        </dict>
        <key>EntryCollectionB</key>
        <dict>
            <key>2's ECB name</key>
            <dict>
                <key>tuuleeun</key>
                <false/>
                <key>batchCodes</key>
                <dict>
                    <key>5564738291</key>
                    <data>
                    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                    </data>
                </dict>
                <key>ImportantDatum7</key>
                <string>sequence identifier</string>
                <key>ImportantDatum8</key>
                <string>three,four</string>
                <key>iDo-aboutThisOne</key>
                <string>thuh-ree</string>
                <key>moreSillyData</key>
                <data>
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                </data>
                <key>subcode</key>
                <integer>841391812</integer>
            </dict>
        </dict>
        <key>ImportantDatum6</key>
        <string>another collection of data</string>
        <key>ImportantDatum7</key>
        <string>identifier string</string>
        <key>ImportantDatum8</key>
        <string>buckle my shoe</string>
        <key>whoCares</key>
        <integer>1</integer>
        <key>iDo-aboutThisOne</key>
        <string>again</string>
        <key>ANDagain</key>
        <string>meeny</string>
        <key>moreSillyData</key>
        <data>
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        </data>
        <key>bucketObits</key>
        <string>say what you want</string>
        <key>amount</key>
        <integer>51736576</integer>
        <key>code</key>
        <integer>456789012</integer>
        <key>subcode</key>
        <integer>841391812</integer>
    </dict>
    <key>another main entry</key>
    <dict>
        <key>EntryCollectionA</key>
        <dict>
            <key>5564738291</key>
            <dict>
                <key>wardrobe</key>
                <string>lionWitch</string>
                <key>buuleeun</key>
                <false/>
            </dict>
        </dict>
        <key>ImportantDatum6</key>
        <string>my third data set</string>
        <key>ImportantDatum7</key>
        <string>ID code</string>
        <key>ImportantDatum8</key>
        <string>five,six</string>
        <key>whoCares</key>
        <integer>1</integer>
        <key>iDo-aboutThisOne</key>
        <string>tenAgain</string>
        <key>ANDagain</key>
        <string>miney</string>
        <key>moreSillyData</key>
        <data>
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        </data>
        <key>bucketObits</key>
        <string>more to say</string>
        <key>amount</key>
        <integer>1576960</integer>
        <key>code</key>
        <integer>1248163264</integer>
        <key>subcode</key>
        <integer>842184218</integer>
    </dict>
    <key>final sample</key>
    <dict>
        <key>EntryCollectionA</key>
        <dict>
            <key>5564738291</key>
            <dict>
                <key>wardrobe</key>
                <string>lionWitch</string>
                <key>buuleeun</key>
                <false/>
            </dict>
        </dict>
        <key>EntryCollectionB</key>
        <dict>
            <key>ECB (but for #4?)</key>
            <dict>
                <key>tuuleeun</key>
                <false/>
                <key>batchCodes</key>
                <dict>
                    <key>5564738291</key>
                    <data>
                    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                    </data>
                </dict>
                <key>ImportantDatum7</key>
                <string>name, of sorts</string>
                <key>ImportantDatum8</key>
                <string>nine,ten</string>
                <key>iDo-aboutThisOne</key>
                <string>tenAgain</string>
                <key>moreSillyData</key>
                <data>
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                </data>
                <key>subcode</key>
                <integer>84218421</integer>
            </dict>
            <key>four's second ECB</key>
            <dict>
                <key>tuuleeun</key>
                <false/>
                <key>batchCodes</key>
                <dict>
                    <key>5564738291</key>
                    <data>
                    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                    </data>
                </dict>
                <key>ImportantDatum7</key>
                <string>three is also 7?</string>
                <key>ImportantDatum8</key>
                <string>eight is also four</string>
                <key>iDo-aboutThisOne</key>
                <string>cra-zee</string>
                <key>moreSillyData</key>
                <data>
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                </data>
                <key>subcode</key>
                <integer>474828131</integer>
            </dict>
            <key>369,121518</key>
            <dict>
                <key>tuuleeun</key>
                <false/>
                <key>batchCodes</key>
                <dict>
                    <key>5564738291</key>
                    <data>
                    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                    </data>
                </dict>
                <key>ImportantDatum7</key>
                <string>code name for this item</string>
                <key>ImportantDatum8</key>
                <string>close the door</string>
                <key>iDo-aboutThisOne</key>
                <string>heaven</string>
                <key>moreSillyData</key>
                <data>
                AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
                </data>
                <key>subcode</key>
                <integer>963852741</integer>
            </dict>
        </dict>
        <key>ImportantDatum6</key>
        <string>and here's another group of data</string>
        <key>ImportantDatum7</key>
        <string>code name for this item</string>
        <key>ImportantDatum8</key>
        <string>do it again</string>
        <key>whoCares</key>
        <integer>1</integer>
        <key>iDo-aboutThisOne</key>
        <string>heaven</string>
        <key>ANDagain</key>
        <string>moe</string>
        <key>moreSillyData</key>
        <data>
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        </data>
        <key>bucketObits</key>
        <string>piece of text</string>
        <key>amount</key>
        <integer>19189760</integer>
        <key>code</key>
        <integer>567890123</integer>
        <key>supportedDeviceTypes</key>
        <integer>7</integer>
        <key>subcode</key>
        <integer>303030303</integer>
    </dict>
</dict>
</plist>

Sample-Code.xsl

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="/">
  <html>
  <body>
  <h2>Heading and preliminary stuff</h2>
   <table>
    <tr>
      <th bgcolor="#336699">Main</th>
      <th>count</th>
      <th bgcolor="#3366cc">EntryCollectionB</th>
      <th bgcolor="#339966">EntryCollectionB/<br/>
        ECBImportantDetail3</th>
      <th bgcolor="#3399cc">EntryCollectionB/<br/>
        ECBImportantDetail4</th>
      <th bgcolor="#33cc66">EntryCollectionB/<br/>
        ECBImportantDetail5</th>
      <th bgcolor="#33cc99">ImportantDatum6</th>
      <th bgcolor="#663399">ImportantDatum7</th>
      <th bgcolor="#6633cc">ImportantDatum8</th>
      <th bgcolor="#669933">iDo-aboutThisOne</th>
      <th bgcolor="#6699cc">ANDagain</th>
      <th bgcolor="#66cc33">amount</th>
    </tr>
  <xsl:for-each select="plist/dict/key">
    <tr>
      <td bgcolor="#66cc99"><xsl:value-of select="." /></td>
      <td><xsl:value-of select="count(following-sibling::dict/key[text()='EntryCollectionB']/
                        following-sibling::dict/key)" /></td>
      <td bgcolor="#993366"><xsl:value-of select="following-sibling::dict/key[text()='EntryCollectionB']/
                        following-sibling::dict/key" /></td>
      <td bgcolor="#9933cc"><xsl:value-of select="following-sibling::dict/key[text()='EntryCollectionB']/
                        following-sibling::dict/key/
                        following-sibling::dict/key[text()='ECBImportantDetail3']/
                        following-sibling::string" /></td>
      <td bgcolor="#996633"><xsl:value-of select="following-sibling::dict/key[text()='EntryCollectionB']/
                        following-sibling::dict/key/
                        following-sibling::dict/key[text()='ECBImportantDetail4']/
                        following-sibling::string" /></td>
      <td bgcolor="#9966cc"><xsl:value-of select="following-sibling::dict/key[text()='EntryCollectionB']/
                        following-sibling::dict/key/
                        following-sibling::dict/key[text()='ECBImportantDetail5']/
                        following-sibling::string" /></td>
      <td bgcolor="#99cc33"><xsl:value-of select="following-sibling::dict/key[text()='ImportantDatum6']/
                        following-sibling::string" /></td>
      <td bgcolor="#99cc66"><xsl:value-of select="following-sibling::dict/key[text()='ImportantDatum7']/
                        following-sibling::string" /></td>
      <td bgcolor="#cc3366"><xsl:value-of select="following-sibling::dict/key[text()='ImportantDatum8']/
                        following-sibling::string" /></td>
      <td bgcolor="#cc3399"><xsl:value-of select="following-sibling::dict/key[text()='iDo-aboutThisOne']/
                        following-sibling::string" /></td>
      <td bgcolor="#cc6633"><xsl:value-of select="following-sibling::dict/key[text()='ANDagain']/
                        following-sibling::string" /></td>
      <td bgcolor="#cc6699"><xsl:value-of select="following-sibling::dict/key[text()='amount']/
                        following-sibling::integer" /></td>
    </tr>
    </xsl:for-each>
  </table>
  </body>
  </html>
 </xsl:template>
</xsl:stylesheet>

Sample-Output.html

<!DOCTYPE HTML><html>
   <body>
      <h2>Heading and preliminary stuff</h2>
      <table>
         <tr>
            <th bgcolor="#336699">Main</th>
            <th>count</th>
            <th bgcolor="#3366cc">EntryCollectionB</th>
            <th bgcolor="#339966">EntryCollectionB/<br>
               ECBImportantDetail3</th>
            <th bgcolor="#3399cc">EntryCollectionB/<br>
               ECBImportantDetail4</th>
            <th bgcolor="#33cc66">EntryCollectionB/<br>
               ECBImportantDetail5</th>
            <th bgcolor="#33cc99">ImportantDatum6</th>
            <th bgcolor="#663399">ImportantDatum7</th>
            <th bgcolor="#6633cc">ImportantDatum8</th>
            <th bgcolor="#669933">iDo-aboutThisOne</th>
            <th bgcolor="#6699cc">ANDagain</th>
            <th bgcolor="#66cc33">amount</th>
         </tr>
         <tr>
            <td bgcolor="#66cc99">Entry1</td>
            <td>7</td>
            <td bgcolor="#993366">Identifier for the first ECB</td>
            <td bgcolor="#9933cc">three</td>
            <td bgcolor="#996633">four</td>
            <td bgcolor="#9966cc">five</td>
            <td bgcolor="#99cc33">what this data pertains to</td>
            <td bgcolor="#99cc66">reference code</td>
            <td bgcolor="#cc3366">one,two</td>
            <td bgcolor="#cc3399">999</td>
            <td bgcolor="#cc6633">eeny</td>
            <td bgcolor="#cc6699">66645714</td>
         </tr>
         <tr>
            <td bgcolor="#66cc99">second entry</td>
            <td>4</td>
            <td bgcolor="#993366">2's ECB name</td>
            <td bgcolor="#9933cc"></td>
            <td bgcolor="#996633"></td>
            <td bgcolor="#9966cc"></td>
            <td bgcolor="#99cc33">another collection of data</td>
            <td bgcolor="#99cc66">identifier string</td>
            <td bgcolor="#cc3366">buckle my shoe</td>
            <td bgcolor="#cc3399">again</td>
            <td bgcolor="#cc6633">meeny</td>
            <td bgcolor="#cc6699">51736576</td>
         </tr>
         <tr>
            <td bgcolor="#66cc99">another main entry</td>
            <td>3</td>
            <td bgcolor="#993366">ECB (but for #4?)</td>
            <td bgcolor="#9933cc"></td>
            <td bgcolor="#996633"></td>
            <td bgcolor="#9966cc"></td>
            <td bgcolor="#99cc33">my third data set</td>
            <td bgcolor="#99cc66">ID code</td>
            <td bgcolor="#cc3366">five,six</td>
            <td bgcolor="#cc3399">tenAgain</td>
            <td bgcolor="#cc6633">miney</td>
            <td bgcolor="#cc6699">1576960</td>
         </tr>
         <tr>
            <td bgcolor="#66cc99">final sample</td>
            <td>3</td>
            <td bgcolor="#993366">ECB (but for #4?)</td>
            <td bgcolor="#9933cc"></td>
            <td bgcolor="#996633"></td>
            <td bgcolor="#9966cc"></td>
            <td bgcolor="#99cc33">and here's another group of data</td>
            <td bgcolor="#99cc66">code name for this item</td>
            <td bgcolor="#cc3366">do it again</td>
            <td bgcolor="#cc3399">heaven</td>
            <td bgcolor="#cc6633">moe</td>
            <td bgcolor="#cc6699">19189760</td>
         </tr>
      </table>
   </body>
</html>

Desired-Output.html

<!DOCTYPE HTML><html>
   <body>
      <h2>Heading and preliminary stuff</h2>
      <table>
         <tr>
            <th bgcolor="#336699">Main</th>
            <th>count</th>
            <th bgcolor="#3366cc">EntryCollectionB</th>
            <th bgcolor="#339966">EntryCollectionB/<br>
               ECBImportantDetail3</th>
            <th bgcolor="#3399cc">EntryCollectionB/<br>
               ECBImportantDetail4</th>
            <th bgcolor="#33cc66">EntryCollectionB/<br>
               ECBImportantDetail5</th>
            <th bgcolor="#33cc99">ImportantDatum6</th>
            <th bgcolor="#663399">ImportantDatum7</th>
            <th bgcolor="#6633cc">ImportantDatum8</th>
            <th bgcolor="#669933">iDo-aboutThisOne</th>
            <th bgcolor="#6699cc">ANDagain</th>
            <th bgcolor="#66cc33">amount</th>
         </tr>
         <tr>
            <td bgcolor="#66cc99">another main entry</td>
            <td>3</td>
            <td bgcolor="#993366">ECB (but for #4?)</td>
            <td bgcolor="#9933cc"></td>
            <td bgcolor="#996633"></td>
            <td bgcolor="#9966cc"></td>
            <td bgcolor="#99cc33">my third data set</td>
            <td bgcolor="#99cc66">ID code</td>
            <td bgcolor="#cc3366">five,six</td>
            <td bgcolor="#cc3399">tenAgain</td>
            <td bgcolor="#cc6633">miney</td>
            <td bgcolor="#cc6699">1576960</td>
         </tr>
         <tr>
            <td bgcolor="#66cc99">Entry1</td>
            <td>7</td>
            <td bgcolor="#993366">Identifier for the first ECB</td>
            <td bgcolor="#9933cc">three</td>
            <td bgcolor="#996633">four</td>
            <td bgcolor="#9966cc">five</td>
            <td bgcolor="#99cc33">what this data pertains to</td>
            <td bgcolor="#99cc66">reference code</td>
            <td bgcolor="#cc3366">one,two</td>
            <td bgcolor="#cc3399">999</td>
            <td bgcolor="#cc6633">eeny</td>
            <td bgcolor="#cc6699">66645714</td>
         </tr>
         <tr>
            <td bgcolor="#66cc99">final sample</td>
            <td>3</td>
            <td bgcolor="#993366">ECB (but for #4?)</td>
            <td bgcolor="#9933cc"></td>
            <td bgcolor="#996633"></td>
            <td bgcolor="#9966cc"></td>
            <td bgcolor="#99cc33">and here's another group of data</td>
            <td bgcolor="#99cc66">code name for this item</td>
            <td bgcolor="#cc3366">do it again</td>
            <td bgcolor="#cc3399">heaven</td>
            <td bgcolor="#cc6633">moe</td>
            <td bgcolor="#cc6699">19189760</td>
         </tr>
         <tr>
            <td bgcolor="#66cc99">second entry</td>
            <td>4</td>
            <td bgcolor="#993366">2's ECB name</td>
            <td bgcolor="#9933cc"></td>
            <td bgcolor="#996633"></td>
            <td bgcolor="#9966cc"></td>
            <td bgcolor="#99cc33">another collection of data</td>
            <td bgcolor="#99cc66">identifier string</td>
            <td bgcolor="#cc3366">buckle my shoe</td>
            <td bgcolor="#cc3399">again</td>
            <td bgcolor="#cc6633">meeny</td>
            <td bgcolor="#cc6699">51736576</td>
         </tr>
      </table>
   </body>
</html>

The people providing the data I'm working with have now decided not to sort the data file, so I have to do it myself. Adding <xsl:sort select="plist/dict/key"> or <xsl:sort select="."> after the <xsl:for-each select="plist/dict/key"> doesn't work, and VS Code is only telling me there's an "XSLT compile error", but not telling what that error is. Does anyone know what the problem with this could be? Or, is there a way to get more info about this out of VSC?

CodePudding user response:

I think to sort by the value of the key element you are correct to use the expression . on the xsl:sort element, because it's evaluated relative to each result of the select expression on the parent for-each.

I suspect your error is that you say you have:

<xsl:sort select=".">

... instead of:

<xsl:sort select="."/>

(Note the slash at the end of the element)

  • Related