Multi layer conditional wrap HTML with XSLT

2019-03-06 15:46发布

问题:

In my Umbraco CMS site, I'm making a list of node "widgets" for content editors to use, with a list of many options they can toggle to change the display. This often involves wrapping an element with an anchor, div, or something else. Using XSLT to display these from the XML output, I've put together what a kludge approach as I'm a very new XSLT beginner.

What I've come to as a solution is multiple nested apply-templates. This creates a large list of conditions, often asking repeat checks, which trees out pretty huge. It's a bit of a nightmare to manage.

It looks as such (but with more than two options in each choose):

<xsl:template match="/">
<xsl:choose>
    <xsl:when test="type='1'">
        <xsl:apply-templates select="widgetContent" mode="type_1" />
    </xsl:when>
    <xsl:otherwise>
        <xsl:apply-templates select="widgetContent" mode="type_default" />
    </xsl:otherwise>
</xsl:choose>
</xsl:template>

<xsl:template match="wigetContent" mode="type_1">
<xsl:choose>
    <xsl:when test="./wrap_with_hyperlink != 0">
        <xsl:element name="a">
        <xsl:apply-templates select="." mode="hyperlink_wrapped" />
        </xsl:element>
    </xsl:when>
    <xsl:otherwise>
        <xsl:apply-templates select="widgetContent" mode="not_hyperlink_wrapped" />
    </xsl:otherwise>
</xsl:choose>
</xsl:template>

What can I do to reduce this tangled mess? I've structured the conditions to be as top down as much as possible, but there are definitely repeated checks where type_2 has to ask the same questions as type_1 all over again.

(edit: clarity) Because the design is basically an onion, type_1 is wrapped by certain tags, type_2 is wrapped by different tags. Next layer in, both could be wrapped by the same tags, and so forth. What would be perfect is:

<xsl:if test="this_wrap_style = 1"><xsl:element name="abc"></xsl:if>
<xsl:if test="this_wrap_style = 2"><xsl:element name="xyz"></xsl:if>
(everything else) 
</abc> //if it exist.
</xyz> //etc

Which definitely doesn't work.

Some of this has been reduced by using Umbraco Doc Types for different widget controls, but part of the nature is that to the ideal structure for content editors is selecting a box widget will give them 5 different types of widget boxes (or more) to choose from, and a coherent back end isn't as important.

Thank you all for your time.

回答1:

 <!--Store data in processing instruction nodes in a separate XML file-->
 <?xml version='1.0' encoding="utf-8"?>
 <root>
   <?_1 div?>
   <?_2 p?>
 </root>

type_1 is wrapped by certain tags, type_2 is wrapped by different tags.

 <xsl:variable name="divider" select="document('condition.xml')//processing-instruction(concat('_', $type) )" />
 <xsl:variable name="equalizer" select="'span'"/>
 <xsl:element name="{$divider}">
 ...
 </xsl:element>

Next layer in, both could be wrapped by the same tags

 <xsl:if test="contains('1,2',$type)">
   <xsl:element name="{$equalizer}">
   ...
   </xsl:element>
 </xsl:if>


标签: xslt