XSL 将具有属性的 xml 行转换为无序列表树视图
XSL transform xml rows with attributes to unordered list treeview
我有以下 XML 来自 SharePoint 控件。我想使用 XSLT 进行转换以生成嵌套的 ul>li 列表。但是我在迭代每一行时遇到问题,主文件夹对每一行重复,而不是创建一个主文件夹节点并在该节点下添加 Menu_Display_name 的值以模拟树视图...
我的 XML 就像:
<dsQueryResponse>
<NewDataSet>
<Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ CORP HR TIME SELF SERVICE" SECONDARY_FOLDER="Time" MENU_DISPLAY_NAME="Create Timecard"></Row>
<Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ CORP HR TIME SELF SERVICE" SECONDARY_FOLDER="Time" MENU_DISPLAY_NAME="Recent Timecards"></Row>
<Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ CORP HR TIME SELF SERVICE" SECONDARY_FOLDER="Time" MENU_DISPLAY_NAME="Templates"></Row>
<Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ CORP HR TIME SELF SERVICE" SECONDARY_FOLDER="Time" MENU_DISPLAY_NAME="Timecard Search"></Row>
<Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ CORP EXP ENTRY" SECONDARY_FOLDER="" MENU_DISPLAY_NAME="Expenses Home"></Row>
<Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ HR EMP SELF SERVICE" SECONDARY_FOLDER="" MENU_DISPLAY_NAME="Accommodation Request"></Row>
<Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ HR EMP SELF SERVICE" SECONDARY_FOLDER="" MENU_DISPLAY_NAME="Additional Personal Information" ></Row>
<Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ HR EMP SELF SERVICE" SECONDARY_FOLDER="" MENU_DISPLAY_NAME="All Actions Awaiting Your Attention"></Row>
<Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ HR EMP SELF SERVICE" SECONDARY_FOLDER="" MENU_DISPLAY_NAME="Appraisals"></Row>
</NewDataSet>
</dsQueryResponse>
我在 XSL 的 "Poor man's attempt" 是这样的:
<xsl:template name="dvt_1.body">
<xsl:param name="Rows" />
<xsl:param name="FirstRow" />
<xsl:param name="LastRow" />
<ul>
<xsl:for-each select="$Rows">
<xsl:if test="position() >= $FirstRow and position() <= $LastRow">
<xsl:call-template name="dvt_1.rowview" />
</xsl:if>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template name="dvt_1.rowview">
<li class="isFolder isExpanded">
<xsl:value-of select="@PRIMARY_FOLDER" />
<xsl:choose>
<xsl:when test="@SECONDARY_FOLDER != ''">
<ul>
<li class="isFolder isExpanded">
<xsl:value-of select="@SECONDARY_FOLDER" />
<ul>
<li><xsl:value-of select="@MENU_DISPLAY_NAME" /></li>
</ul>
</li>
</ul>
</xsl:when>
<xsl:otherwise>
<ul>
<li><xsl:value-of select="@MENU_DISPLAY_NAME" /></li>
</ul>
</xsl:otherwise>
</xsl:choose>
</li>
</xsl:template>
我想要的 xsl 输出是这样的:
<div id="navigator">
<ul>
<li class="isFolder isExpanded">
XYZ CORP HR TIME SELF SERVICE
<ul>
<li class="isFolder isExpanded">
Time
<ul>
<li><a href="#" target="_tab">Create Timecard</a></li>
<li><a href="#" target="_tab">Recent Timecards</a></li>
<li><a href="#" target="_tab">Templates</a></li>
<li><a href="#" target="_tab">Timecard Search</a></li>
</ul>
</li>
</ul>
</li>
<li class="isFolder isExpanded">
XYZ CORP EXP ENTRY
<ul>
<li><a href="#" target="_tab">Expense Home</a></li>
</ul>
</li>
<li class="isFolder isExpanded">
XYZ HR EMP SELF SERVICE
<ul>
<li><a href="#" target="_tab">Accommodation Request</a></li>
<li><a href="#" target="_tab">Additional Personal Information</a></li>
<li><a href="#" target="_tab">All Actions Awaiting Your Attention</a></li>
<li><a href="#" target="_tab">Appraisals</a></li>
</ul>
</li>
</ul>
</div>
有人可以帮我用 xslt 实现这个吗?
Muenchian grouping 确实是您需要在 XSLT 1.0 中查看的内容(我相信这是 Sharepoint 使用的内容)。首先你按 PRIMARY_VALUE
属性分组,所以你有一个像这样的键:
<xsl:key name="primary" match="Row" use="@PRIMARY_FOLDER" />
但我假设对于给定的 PRIMARY_VALUE
,您可能有多个 SECONDARY_FOLDER
,因此您需要第二个密钥:
<xsl:key name="secondary" match="Row" use="concat(@PRIMARY_FOLDER, '|', @SECONDARY_FOLDER)" />
您从 select 第一次出现每个 PRIMARY_FOLDER
值的行开始
<xsl:for-each select="$rows[generate-id() = generate-id(key('primary', @PRIMARY_FOLDER)[1])]">
然后在其中 select 具有不同 SECONDARY_VALUE
的行构成嵌套列表的基础
<xsl:apply-templates select="key('primary', @PRIMARY_FOLDER)[generate-id() = generate-id(key('secondary', concat(@PRIMARY_FOLDER, '|', @SECONDARY_FOLDER))[1])]" mode="secondary" />
唯一的额外工作是,根据是否填充 SECONDARY_FOLDER
,您的行为会略有不同。不过,您可以使用两个单独的模板来完成此操作。
试试这个 XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" indent="yes" />
<xsl:key name="primary" match="Row" use="@PRIMARY_FOLDER" />
<xsl:key name="secondary" match="Row" use="concat(@PRIMARY_FOLDER, '|', @SECONDARY_FOLDER)" />
<xsl:variable name="rows" select="//Row" />
<xsl:template match="/">
<ul>
<xsl:for-each select="$rows[generate-id() = generate-id(key('primary', @PRIMARY_FOLDER)[1])]">
<li class="isFolder isExpanded">
<xsl:value-of select="@PRIMARY_FOLDER" />
<xsl:apply-templates select="key('primary', @PRIMARY_FOLDER)[generate-id() = generate-id(key('secondary', concat(@PRIMARY_FOLDER, '|', @SECONDARY_FOLDER))[1])]" mode="secondary" />
</li>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template match="Row[@SECONDARY_FOLDER != '']" mode="secondary">
<li class="isFolder isExpanded">
<xsl:value-of select="@SECONDARY_FOLDER" />
<ul>
<xsl:apply-templates select="key('secondary', concat(@PRIMARY_FOLDER, '|', @SECONDARY_FOLDER))" />
</ul>
</li>
</xsl:template>
<xsl:template match="Row" mode="secondary">
<xsl:apply-templates select="key('primary', @PRIMARY_FOLDER)" />
</xsl:template>
<xsl:template match="Row">
<li>
<a href="#" target="_tab">
<xsl:value-of select="@MENU_DISPLAY_NAME" />
</a>
</li>
</xsl:template>
</xsl:stylesheet>
在 http://xsltransform.net/pPzifq9 上查看实际操作。
请注意,如果您的实际 XML 有命名空间,您需要修改 XSLT 以将这些考虑在内。
我有以下 XML 来自 SharePoint 控件。我想使用 XSLT 进行转换以生成嵌套的 ul>li 列表。但是我在迭代每一行时遇到问题,主文件夹对每一行重复,而不是创建一个主文件夹节点并在该节点下添加 Menu_Display_name 的值以模拟树视图... 我的 XML 就像:
<dsQueryResponse>
<NewDataSet>
<Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ CORP HR TIME SELF SERVICE" SECONDARY_FOLDER="Time" MENU_DISPLAY_NAME="Create Timecard"></Row>
<Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ CORP HR TIME SELF SERVICE" SECONDARY_FOLDER="Time" MENU_DISPLAY_NAME="Recent Timecards"></Row>
<Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ CORP HR TIME SELF SERVICE" SECONDARY_FOLDER="Time" MENU_DISPLAY_NAME="Templates"></Row>
<Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ CORP HR TIME SELF SERVICE" SECONDARY_FOLDER="Time" MENU_DISPLAY_NAME="Timecard Search"></Row>
<Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ CORP EXP ENTRY" SECONDARY_FOLDER="" MENU_DISPLAY_NAME="Expenses Home"></Row>
<Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ HR EMP SELF SERVICE" SECONDARY_FOLDER="" MENU_DISPLAY_NAME="Accommodation Request"></Row>
<Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ HR EMP SELF SERVICE" SECONDARY_FOLDER="" MENU_DISPLAY_NAME="Additional Personal Information" ></Row>
<Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ HR EMP SELF SERVICE" SECONDARY_FOLDER="" MENU_DISPLAY_NAME="All Actions Awaiting Your Attention"></Row>
<Row DOMAIN_USERNAME="someUser" PRIMARY_FOLDER="XYZ HR EMP SELF SERVICE" SECONDARY_FOLDER="" MENU_DISPLAY_NAME="Appraisals"></Row>
</NewDataSet>
</dsQueryResponse>
我在 XSL 的 "Poor man's attempt" 是这样的:
<xsl:template name="dvt_1.body">
<xsl:param name="Rows" />
<xsl:param name="FirstRow" />
<xsl:param name="LastRow" />
<ul>
<xsl:for-each select="$Rows">
<xsl:if test="position() >= $FirstRow and position() <= $LastRow">
<xsl:call-template name="dvt_1.rowview" />
</xsl:if>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template name="dvt_1.rowview">
<li class="isFolder isExpanded">
<xsl:value-of select="@PRIMARY_FOLDER" />
<xsl:choose>
<xsl:when test="@SECONDARY_FOLDER != ''">
<ul>
<li class="isFolder isExpanded">
<xsl:value-of select="@SECONDARY_FOLDER" />
<ul>
<li><xsl:value-of select="@MENU_DISPLAY_NAME" /></li>
</ul>
</li>
</ul>
</xsl:when>
<xsl:otherwise>
<ul>
<li><xsl:value-of select="@MENU_DISPLAY_NAME" /></li>
</ul>
</xsl:otherwise>
</xsl:choose>
</li>
</xsl:template>
我想要的 xsl 输出是这样的:
<div id="navigator">
<ul>
<li class="isFolder isExpanded">
XYZ CORP HR TIME SELF SERVICE
<ul>
<li class="isFolder isExpanded">
Time
<ul>
<li><a href="#" target="_tab">Create Timecard</a></li>
<li><a href="#" target="_tab">Recent Timecards</a></li>
<li><a href="#" target="_tab">Templates</a></li>
<li><a href="#" target="_tab">Timecard Search</a></li>
</ul>
</li>
</ul>
</li>
<li class="isFolder isExpanded">
XYZ CORP EXP ENTRY
<ul>
<li><a href="#" target="_tab">Expense Home</a></li>
</ul>
</li>
<li class="isFolder isExpanded">
XYZ HR EMP SELF SERVICE
<ul>
<li><a href="#" target="_tab">Accommodation Request</a></li>
<li><a href="#" target="_tab">Additional Personal Information</a></li>
<li><a href="#" target="_tab">All Actions Awaiting Your Attention</a></li>
<li><a href="#" target="_tab">Appraisals</a></li>
</ul>
</li>
</ul>
</div>
有人可以帮我用 xslt 实现这个吗?
Muenchian grouping 确实是您需要在 XSLT 1.0 中查看的内容(我相信这是 Sharepoint 使用的内容)。首先你按 PRIMARY_VALUE
属性分组,所以你有一个像这样的键:
<xsl:key name="primary" match="Row" use="@PRIMARY_FOLDER" />
但我假设对于给定的 PRIMARY_VALUE
,您可能有多个 SECONDARY_FOLDER
,因此您需要第二个密钥:
<xsl:key name="secondary" match="Row" use="concat(@PRIMARY_FOLDER, '|', @SECONDARY_FOLDER)" />
您从 select 第一次出现每个 PRIMARY_FOLDER
值的行开始
<xsl:for-each select="$rows[generate-id() = generate-id(key('primary', @PRIMARY_FOLDER)[1])]">
然后在其中 select 具有不同 SECONDARY_VALUE
的行构成嵌套列表的基础
<xsl:apply-templates select="key('primary', @PRIMARY_FOLDER)[generate-id() = generate-id(key('secondary', concat(@PRIMARY_FOLDER, '|', @SECONDARY_FOLDER))[1])]" mode="secondary" />
唯一的额外工作是,根据是否填充 SECONDARY_FOLDER
,您的行为会略有不同。不过,您可以使用两个单独的模板来完成此操作。
试试这个 XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" indent="yes" />
<xsl:key name="primary" match="Row" use="@PRIMARY_FOLDER" />
<xsl:key name="secondary" match="Row" use="concat(@PRIMARY_FOLDER, '|', @SECONDARY_FOLDER)" />
<xsl:variable name="rows" select="//Row" />
<xsl:template match="/">
<ul>
<xsl:for-each select="$rows[generate-id() = generate-id(key('primary', @PRIMARY_FOLDER)[1])]">
<li class="isFolder isExpanded">
<xsl:value-of select="@PRIMARY_FOLDER" />
<xsl:apply-templates select="key('primary', @PRIMARY_FOLDER)[generate-id() = generate-id(key('secondary', concat(@PRIMARY_FOLDER, '|', @SECONDARY_FOLDER))[1])]" mode="secondary" />
</li>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template match="Row[@SECONDARY_FOLDER != '']" mode="secondary">
<li class="isFolder isExpanded">
<xsl:value-of select="@SECONDARY_FOLDER" />
<ul>
<xsl:apply-templates select="key('secondary', concat(@PRIMARY_FOLDER, '|', @SECONDARY_FOLDER))" />
</ul>
</li>
</xsl:template>
<xsl:template match="Row" mode="secondary">
<xsl:apply-templates select="key('primary', @PRIMARY_FOLDER)" />
</xsl:template>
<xsl:template match="Row">
<li>
<a href="#" target="_tab">
<xsl:value-of select="@MENU_DISPLAY_NAME" />
</a>
</li>
</xsl:template>
</xsl:stylesheet>
在 http://xsltransform.net/pPzifq9 上查看实际操作。
请注意,如果您的实际 XML 有命名空间,您需要修改 XSLT 以将这些考虑在内。