But in all, I would say that if you have any influence on the input
XML, then you should change it. There is nothing in the structures or
attributes that tells that "sb:title" is the child of
"sb:contribution" instead of "sb:authors". This makes a generic
solution impossible.
I have scetched a more generic solution which does not at all do what
you require, but I hope this is some inspiration. Namely, it does not
have an "before host" and "after host" part.
<xsl:template match="root">
<xsl:apply-templates select="p[bookmark-start]" mode="bookmark"/>
</xsl:template>
<xsl:template match="p" mode="bookmark">
<xsl:element name="{user-field[1]/@name}">
<xsl:apply-templates
select="following-sibling::p[preceding-sibling::p[bookmark-start[@id=current(
)/@id]]"
mode="children"/> <!-- Should be a key -->
</xsl:element>
</xsl:template>
<!-- Should have two templates, one for before host, and one for after host
-->
<xsl:template match="p" mode="children">
<xsl:element name="{user-field[1]/@name}">
<xsl:choose>
<xsl:when test="user-field[position()>1]"> <!-- more
user-fields => leaf -->
<xsl:apply-templates select="user-field[position()>1]"
mode="leaf"/>
</xsl:when>
<xsl:otherwise>
<!-- More logical children. Caveat about "host" element applies -->
<xsl:apply-templates
select="following-sibling::p[preceding-sibling::p[bookmark-start[@id=current(
)/@id]]"
mode="children"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="user-field" mode="leaf">
<xsl:element name="{@name}">
<xsl:value-of select="following-sibling::user-text"/>
</xsl:element>
</xsl:template>
I hope this is some help for your problem.
Regards,
Ragulf Pickaxe :-)