How does one incorporate a test for the first value prior to running the loop to extract all the values?
This part, I'm not sure yet. I'm kinda just figuring this out as I go. I know a bit about HTML, XML, programming in general, but I'm no expert.
To test for the first value, I tried wrapping the whole for-each loop in an if-test element... but that didn't work. The resulting HTML element just ended up being blank. Couldn't find a way to make that work. So that's why I wrote it how I did above.
If a task doesn't have any <TAG> children, the for-each loop still seems to work on its own without any "test" needed (it doesn't break or cause any errors, at least). So maybe the for-each loop has some sort of error-checking built in? Maybe if the for-each finds the element count = 0, it produces the same result as if you ran a <xsl:if test="*"> that didn't find anything. I don't know if this produces a result of "null" or "NaN" or "0" or "" (empty string) -- I have no idea what is happening internally when the for-each loop doesn't find any matching elements, but it seems to just move forward anyway without errors.
This would make sense, I think. Since the for-each loop runs "for each" element it finds, the loop itself must "know" how many "each" exist. Otherwise it wouldn't be a for-each loop, it'd be a regular for-while loop (which can run infinitely). And I don't think XSL even has for-while loops.
I ran this XSLT on a larger TDL file of mine with over 1000 tasks (some with tags, most have no tags), and the XSLT worked fine, no errors. Any task with TAGS would have them written to the HTML file under the proper <td> elements I assigned it, and any tasks that didn't have TAGS would just leave that area blank and proceed to the next task.
This is as far as I've figured out so far. I'm not sure if my XSL syntax is "correct" or "efficient" or would be considered "best practices" or not -- but it seems to work and produce a working HTML file for my purposes, and that's good enough for me.
I did a little searching on W3C, and it seems like you don't need to "test" a for-each loop. The for-each loop will "crawl the XML tree" and seems to naturally end when it hits the last element in your selection scope.
https://www.w3schools.com/xml/xsl_for_each.asp
The page I just linked also shows an example of filtering a list by certain criteria (basically the same thing I did for TDL's <TAG> elements).
I did a bit more tinkering, and apparently you can filter a for-each loop with AND/OR as well.
Go to this link
https://www.w3schools.com/xml/tryxslt.a ... log_filter , and copy/paste the bellow code into the right window.
Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
<th>Country</th>
</tr>
<xsl:for-each select="(catalog/cd[artist='Bob Dylan' or country='UK'])">
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="artist"/></td>
<td><xsl:value-of select="country"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
This will only print out any musician named 'Bob Dylan' OR any musician from the UK. The key line I changed is here:
Code: Select all
<xsl:for-each select="(catalog/cd[artist='Bob Dylan' or country='UK'])">
That's all that needs to be modified in order to filter multiple criteria. So it's apparently possible to set up some complex filtering with a single for-each loop. Considering I was able to filter by 'artist' or 'country in one loop, you could probably do the same with a TDL file, and use a single for-each loop to check for multiple TAG, CATEGORY, and FILEREFPATH elements all at once.