I am trying to understand how XSLT can iterate over multiple elements and output data from the those elements and their older and younger siblings. See the example below:
<a>
<b name="first">
<c value="C Value">C Text</c>
<d>D1 Text</d>
<d>D2 Text</d>
<e>E Text</e>
</b>
<b name="second">
<c value="C Value">C Text</c>
<d>D1 Text</d>
<d>D2 Text</d>
<d>D3 Text</d>
<e>E Text</e>
</b>
<b name="third">
<c value="C Value">C Text</c>
<e>E Text</e>
</b>
</a>
I would like the output to be like the following (assuming for simplicity that each element's text will not contain commas).
first,C Value,C Text,D1 Text,E Text
first,C Value,C Text,D2 Text,E Text
second,C Value,C Text,D1 Text,E Text
second,C Value,C Text,D2 Text,E Text
second,C Value,C Text,D3 Text,E Text
third,C Value,C Text,,E Text
So there could be an arbitrary number of <d> elements (or none at all). Each CSV line must contain the information from <c> (the older sibling of <d>), the information from one instance of <d>, and the information from <e>, the younger sibling of <d>. (I may be making up this notion of younger and older, but it seems to make sense.)
I haven't worked with XSLT before, so I really don't know where to start with it. The examples I've found for iterating over elements do not make it clear how I can pull values from later in the document (e.g. <e> in the example) and return to another instance of the element (e.g. <d>). I've written an implementation of this in Python with lxml, but would like to see if XSLT is better suited for this transformation.
EDIT:
I just saw that an answer was posted which I will be studying in detail to try to understand it. But just to share what I've been working on, here is the XSL that I have been developing. It fails to output anything when there is no <d> value.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" encoding="iso-8859-1" />
<xsl:strip-space elements="*" />
<xsl:template match="a">
<xsl:for-each select="b">
<xsl:call-template name="match-b"/>
</xsl:for-each>
<xsl:text> </xsl:text>
</xsl:template>
<xsl:template name="match-b" match="b">
<xsl:for-each select="d">
<xsl:value-of select="../@name"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="../c/@value"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="../c"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="."/>
<xsl:text>,</xsl:text>
<xsl:value-of select="../e"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Output:
first,C value,C Text,D1 Text,E Text
first,C value,C Text,D2 Text,E Text
second,C value,C Text,D1 Text,E Text
second,C value,C Text,D2 Text,E Text
second,C value,C Text,D3 Text,E Text
delements, that would require an intermediary step that create adwithin thoseb[not(d)]elements.