Thank you for the files and no worries: I like puzzles. I haven't had to work with XSLT for so long that I've become rusty and this seems like a fun little distraction.
You're getting unexpected additional output because you probably didn't know that there's such a thing as a default template. The default template basically copies everything it finds that is not matched by another template. In your case, only the <PERSON> and <TAG> elements contain text and that's what you see. If, for example, you put some text right before the closing </TODOLIST> tag, that would appear as well.
That should no longer be a problem with the following transformation, which suppresses everything unless it's explicitly handled by a template. It also looked like you wanted to use TAB delimiters, so I added those instead of the spaces and used the newline character at the end.
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:output method="text" encoding="utf-8"/>
<xsl:template match="TODOLIST/TASK/TASK">
<xsl:value-of select="./PERSON"/>
<xsl:text>	</xsl:text>
<!-- use TAB delimiters -->
<xsl:value-of select="../@TITLE"/>
<xsl:text>	</xsl:text>
<xsl:value-of select="./@TITLE"/>
<xsl:text>	</xsl:text>
<xsl:value-of select="./@STARTDATESTRING"/>
<xsl:text>	</xsl:text>
<xsl:value-of select="./@DUEDATESTRING"/>
<xsl:text>
</xsl:text>
<!-- newline character -->
</xsl:template>
<!-- ignore all -->
<xsl:template match="*|@*|comment()|processing-instruction()|text()">
<xsl:apply-templates select="*|@*|comment()|processing-instruction()|text()"/>
</xsl:template>
</xsl:stylesheet>
What I still don't understand is the part where you're expecting some kind of filtering. You might have to elaborate on that.
Right now, the template does exactly what you're asking it to. Whenever it finds a path that matches "TODOLIST/TASK/TASK", it dives into the template. It then outputs the value of the PERSON child followed by the delimiter. Afterwards, it looks at the parent node and outputs its TITLE attribute, and so forth.
What elements do you expect to be filtered out based on what condition?