简体   繁体   中英

XSLT Transforming XML into a cross referenced, nested HTML lists when source nodes are siblings and nesting is based on attribute values

Problem: I need to create a nested HTML unordered list from XML this is not nested. Additionally I need to cross reference the XML with an 'allowed nodes' section that is also contained in the document.

Example XML:

<content>
  <data>
    <navigation>
      <link name="about us" url="#"/>
      <link name="staff" url="staff.asp" parent="about us"/>
      <link name="contact" url="contact.asp" parent="about us"/>
      <link name="facebook" url="facebook.asp"/>
    </navigation>
  </data>
  <allowedlinks>
    <link name="about us"/>       
    <link name="facebook"/>
  </allowedlinks>
</content>

Example Result HTML (note I have left out the boiler plate code):

<ul>
    <li>
      about us
      <ul>
        <li>staff</li>
        <li>contact</li>
      </ul>
    </li>
    <li>facebook</li>
</ul>

Ultimately this will form a nav menu on a site.

Rules: -I need to use XSLT 1.0 to create a solution.

-If a link exists, I need to add it to the UL and create any nested child UL's if any siblings contain a @parent of the current nodes @name.

-Before generating the LI item of any node that does not have a @parent, it must first be confirmed that its @name matches a link @name in the allowed links section.

In my opinion - the structure of the XML being transformed is really stupid and makes the transform process overly complex - however since I am unable to change the original XML, I need a solution.

Note - I do already have an answer which works okay, I will post it shortly. I wanted to see other possible answers first :)

Bonus if this can be done with template matching and not too many for each loops.

My solution contains 2 nested for-each's which I do not like.

This is a classic case for using keys :

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:key name="allowed-link" match="allowedlinks/link" use="@name" />
<xsl:key name="link-by-parent" match="link" use="@parent" />

<xsl:template match="/content">
    <ul>
        <xsl:apply-templates select="data/navigation/link[not(@parent) and key('allowed-link', @name)]"/>
    </ul>
</xsl:template>

<xsl:template match="link">
    <li>
        <xsl:value-of select="@name"/>
        <xsl:variable name="sublinks" select="key('link-by-parent', @name)" />
        <xsl:if test="$sublinks">
            <ul>
                <xsl:apply-templates select="$sublinks"/>
            </ul>
        </xsl:if>
    </li>
</xsl:template>

</xsl:stylesheet>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM