将兄弟节点视为XSLT Muenchian分组的一个

时间:2015-04-01 11:39:25

标签: xml xslt sharepoint muenchian-grouping

我尝试使用Muenchian分组以分层方式显示公司政策文档。策略文档全部添加到SharePoint,并使用语言,类别和文档类型进行标记。然后我使用它创建的XML。

我需要从2个合并列表中获取数据。 SharePoint的工作方式,我的XML看起来像这样(每个SharePoint列表都有一个Rows元素):我必须简化此操作以删除SP在过去时添加的数百个属性stackoverflowsize限制,但结构准确。

<dsQueryResponse>
  <Rows>
    <Row Title="Testitem" Category="Category 1" Language="English" DocumentType="Content" />
  </Rows>
  <Rows>
    <Row Title="Doc1" Category="Category 1" Language="English" DocumentType="Policy" />
    <Row Title="Policy2" Category="Category 2" Language="English" DocumentType="Policy" />
    <Row Title="Policy3" Category="Category 1" Language="Nederlands (Dutch)" DocumentType="Form" />
  </Rows>
</dsQueryResponse>

当前的xsl如下所示:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:SharePoint="Microsoft.SharePoint.WebControls"
  xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer"
  xmlns:agg="http://schemas.microsoft.com/sharepoint/aggregatesource"
  xmlns:asp="http://schemas.microsoft.com/ASPNET/20"
  xmlns:d="http://schemas.microsoft.com/sharepoint/dsp"
  xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime"
  xmlns:ddwrt2="urn:frontpage:internal"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  xmlns:x="http://www.w3.org/2001/XMLSchema"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xsl msxsl ddwrt" 
  ddwrt:oob="true"
>
  <xsl:output indent="yes" omit-xml-declaration="yes" />
  <xsl:key name="byLANGUAGE" match="/dsQueryResponse/Rows/Row" use="@Language" />
  <xsl:key name="byCATEGORY" match="/dsQueryResponse/Rows/Row" use="concat(@Language, '+', @Category)" />

  <xsl:template match="/">
    <xsl:apply-templates select="/dsQueryResponse/Rows/Row[count(. | key('byLANGUAGE', @Language)[1]) = 1]/@Language">
      <xsl:sort select="." order="ascending" />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="@Language">
    <br /><b>Below you can see all policies in <xsl:value-of select="." /></b><br /><br />
    <xsl:variable name="thisLanguage" select="key('byLANGUAGE', .)" />
    <xsl:apply-templates select="$thisLanguage[count(. | key('byCATEGORY', concat(@Language, '+', @Category))[1])= 1]/@Category">
      <xsl:sort select="." order="ascending" />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="@Category">
    <br />Category: <xsl:value-of select="." />
    <xsl:apply-templates select="key('byCATEGORY', concat(../@Language, '+', .))" />
  </xsl:template>

  <xsl:template match="/dsQueryResponse/Rows/Row">
    <br />Title: <xsl:value-of select="@Title" />
  </xsl:template>
</xsl:stylesheet>

,当前结果看起来像这样(一团糟):

Below you can see all policies in English 

Category: Category 1
Title: Testitem

Category: Category 2
Title: Policy2

Below you can see all policies in English

Category: Category 1
Title: Testitem

Category: Category 2
Title: Policy2

Below you can see all policies in Nederlands (Dutch)

Category: Category 1
Title: Policy3 

**My desired output is:**

Below you can see all policies in English 

Category: Category 1
Title: Testitem
Title: Doc1

Category: Category 2
Title: Policy2

Below you can see all policies in Nederlands (Dutch)

Category: Category 1
Title: Policy3 

所以我似乎得到了大量的重复,大概是因为某些内容被调用了两次,一次是针对每个Rows元素?我是XSL的新手,所以任何帮助都会受到赞赏。

==========更新==========

下面的代码现在适用于我的SharePoint(看起来很庞大的选择语句在技术上是不必要的但我需要它们来摆脱我已经放在顶部的JQuery的非英文字符这个):

完整XSLT:

<xsl:stylesheet xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" xmlns:agg="http://schemas.microsoft.com/sharepoint/aggregatesource" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal" ddwrt:oob="true">

<xsl:output indent="yes" omit-xml-declaration="yes"/>
<xsl:key name="byLANGUAGE" match="/dsQueryResponse/Rows/Row" use="@Language" />
<xsl:key name="byCATEGORY" match="/dsQueryResponse/Rows/Row" use="concat(@Language, '+', @Category)" />

<xsl:template match="/">
<div id="tabs" style="display:none;">
<!--Create tabs-->
<ul>
<xsl:apply-templates select="/dsQueryResponse/Rows/Row[count(. | key('byLANGUAGE', @Language)[2]) = 1]/@Language">
<xsl:sort select="." order="ascending" />
</xsl:apply-templates>
</ul>
<!--Create content-->
<xsl:apply-templates select="/dsQueryResponse/Rows/Row[count(. | key('byLANGUAGE', @Language)[2]) = 1]/@Language" mode="pass2">
<xsl:sort select="." order="ascending" />
</xsl:apply-templates>
</div>
</xsl:template>

<!--Do a first pass to create the tabs -->
<xsl:template match="@Language">
<li>
<xsl:choose>
<xsl:when test=". = 'English'"><xsl:text disable-output-escaping="yes">&lt;a href="#English"&gt;</xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes">&lt;/a&gt;</xsl:text></xsl:when>
<xsl:when test=". = 'Bahasa'"><xsl:text disable-output-escaping="yes">&lt;a href="#Bahasa"&gt;</xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes">&lt;/a&gt;</xsl:text></xsl:when>
<xsl:when test=". = '简体中文 (Chinese)'"><xsl:text disable-output-escaping="yes">&lt;a href="#Chinese"&gt;</xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes">&lt;/a&gt;</xsl:text></xsl:when>
<xsl:when test=". = 'Nederlands (Dutch)'"><xsl:text disable-output-escaping="yes">&lt;a href="#Dutch"&gt;</xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes">&lt;/a&gt;</xsl:text></xsl:when>
<xsl:when test=". = 'Français (French)'"><xsl:text disable-output-escaping="yes">&lt;a href="#French"&gt;</xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes">&lt;/a&gt;</xsl:text></xsl:when>
<xsl:when test=". = 'Deutsch (German)'"><xsl:text disable-output-escaping="yes">&lt;a href="#German"&gt;</xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes">&lt;/a&gt;</xsl:text></xsl:when>
<xsl:when test=". = 'Italiano (Italian)'"><xsl:text disable-output-escaping="yes">&lt;a href="#Italian"&gt;</xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes">&lt;/a&gt;</xsl:text></xsl:when>
<xsl:when test=". = '日本語 (Japanese)'"><xsl:text disable-output-escaping="yes">&lt;a href="#Japanese"&gt;</xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes">&lt;/a&gt;</xsl:text></xsl:when>
<xsl:when test=". = '한국의 (Korean)'"><xsl:text disable-output-escaping="yes">&lt;a href="#Korean"&gt;</xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes">&lt;/a&gt;</xsl:text></xsl:when>
<xsl:when test=". = 'Polski (Polish)'"><xsl:text disable-output-escaping="yes">&lt;a href="#Polish"&gt;</xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes">&lt;/a&gt;</xsl:text></xsl:when>
<xsl:when test=". = 'Português (Portuguese)'"><xsl:text disable-output-escaping="yes">&lt;a href="#Portuguese"&gt;</xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes">&lt;/a&gt;</xsl:text></xsl:when>
<xsl:when test=". = 'PyccĸИЙ (Russian)'"><xsl:text disable-output-escaping="yes">&lt;a href="#Russian"&gt;</xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes">&lt;/a&gt;</xsl:text></xsl:when>
<xsl:when test=". = 'Castellano (Spanish)'"><xsl:text disable-output-escaping="yes">&lt;a href="#Spanish"&gt;</xsl:text><xsl:value-of select="." /><xsl:text disable-output-escaping="yes">&lt;/a&gt;</xsl:text></xsl:when>
</xsl:choose>
</li>
</xsl:template>

<!--and a second pass to do everything else-->
<xsl:template match="@Language" mode="pass2">
<xsl:choose>
<xsl:when test=". = 'English'"><xsl:text disable-output-escaping="yes">&lt;div id="English"&gt;</xsl:text></xsl:when>
<xsl:when test=". = 'Bahasa'"><xsl:text disable-output-escaping="yes">&lt;div id="Bahasa"&gt;</xsl:text></xsl:when>
<xsl:when test=". = '简体中文 (Chinese)'"><xsl:text disable-output-escaping="yes">&lt;div id="Chinese"&gt;</xsl:text></xsl:when>
<xsl:when test=". = 'Nederlands (Dutch)'"><xsl:text disable-output-escaping="yes">&lt;div id="Dutch"&gt;</xsl:text></xsl:when>
<xsl:when test=". = 'Français (French)'"><xsl:text disable-output-escaping="yes">&lt;div id="French"&gt;</xsl:text></xsl:when>
<xsl:when test=". = 'Deutsch (German)'"><xsl:text disable-output-escaping="yes">&lt;div id="German"&gt;</xsl:text></xsl:when>
<xsl:when test=". = 'Italiano (Italian)'"><xsl:text disable-output-escaping="yes">&lt;div id="Italian"&gt;</xsl:text></xsl:when>
<xsl:when test=". = '日本語 (Japanese)'"><xsl:text disable-output-escaping="yes">&lt;div id="Japanese"&gt;</xsl:text></xsl:when>
<xsl:when test=". = '한국의 (Korean)'"><xsl:text disable-output-escaping="yes">&lt;div id="Korean"&gt;</xsl:text></xsl:when>
<xsl:when test=". = 'Polski (Polish)'"><xsl:text disable-output-escaping="yes">&lt;div id="Polish"&gt;</xsl:text></xsl:when>
<xsl:when test=". = 'Português (Portuguese)'"><xsl:text disable-output-escaping="yes">&lt;div id="Portuguese"&gt;</xsl:text></xsl:when>
<xsl:when test=". = 'PyccĸИЙ (Russian)'"><xsl:text disable-output-escaping="yes">&lt;div id="Russian"&gt;</xsl:text></xsl:when>
<xsl:when test=". = 'Castellano (Spanish)'"><xsl:text disable-output-escaping="yes">&lt;div id="Spanish"&gt;</xsl:text></xsl:when>
</xsl:choose>
<b>Below you can see all policies in <xsl:value-of select="." /></b><br /><br/>

<div class="accordion">
<xsl:variable name="thisLanguage" select="key('byLANGUAGE', .)" />
<xsl:apply-templates select="$thisLanguage[count(. | key('byCATEGORY', concat(@Language, '+', @Category))[2])= 1]/@Category">
<xsl:sort select="." order="ascending" />
</xsl:apply-templates>
</div>

<xsl:text disable-output-escaping="yes">&lt;/div&gt;</xsl:text>
</xsl:template>

<xsl:template match="@Category">
<h3>
<xsl:value-of select="." />
</h3>

<div class="accordionContent">
<xsl:apply-templates select="key('byCATEGORY', concat(../@Language, '+', .))"/>
</div>
</xsl:template>

<xsl:template match="/dsQueryResponse/Rows/Row">
<div class="policy-item">
<div class="policy-item-title">
<xsl:value-of select="@Title" />
</div>
<xsl:if test="@ItemHtml != ''">
<div class="policy-item-content">
<xsl:value-of select="@ItemHtml" disable-output-escaping="yes" />
</div>
</xsl:if>
</div>
</xsl:template>

</xsl:stylesheet>

1 个答案:

答案 0 :(得分:1)

以下是我要做的事情:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:SharePoint="Microsoft.SharePoint.WebControls"
  xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer"
  xmlns:agg="http://schemas.microsoft.com/sharepoint/aggregatesource"
  xmlns:asp="http://schemas.microsoft.com/ASPNET/20"
  xmlns:d="http://schemas.microsoft.com/sharepoint/dsp"
  xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime"
  xmlns:ddwrt2="urn:frontpage:internal"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  xmlns:x="http://www.w3.org/2001/XMLSchema"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="msxsl ddwrt SharePoint __designer agg asp d ddwrt2 x" 
  ddwrt:oob="true"
>
  <xsl:output method="html" indent="yes" omit-xml-declaration="yes" />
  <xsl:key name="kRowByLanguage" match="Row" use="@Language" />
  <xsl:key name="kRowByCategory" match="Row" use="concat(@Language, '+', @Category)" />

  <xsl:template match="/">
    <html>
      <body>
        <xsl:apply-templates select="dsQueryResponse/Rows" />
      </body>
    </html>
  </xsl:template>

  <xsl:template match="Rows">
    <xsl:apply-templates mode="language" select="Row[
      count(. | key('kRowByLanguage', @Language)[1]) = 1
    ]">
      <xsl:sort select="@Language" order="ascending" />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="Row" mode="language">
    <xsl:variable name="myCategory" select="concat(@Language, '+', @Category)" />
    <div class="language">
      <div>
        <xsl:text>Below you can see all policies in </xsl:text>
        <xsl:value-of select="@Language" />
      </div>
      <div>
        <xsl:apply-templates mode="category" select="key('kRowByLanguage', @Language)[
            count(. | key('kRowByCategory', $myCategory)[1]) = 1
        ]">
          <xsl:sort select="@Category" order="ascending" />
        </xsl:apply-templates>
      </div>
    </div>
  </xsl:template>

  <xsl:template match="Row" mode="category">
    <xsl:variable name="myCategory" select="concat(@Language, '+', @Category)" />
    <div class="catecory">
      <div>
        <xsl:text>Category: </xsl:text>
        <xsl:value-of select="@Category" />
      </div>
      <div>
        <xsl:apply-templates mode="title" select="key('kRowByCategory', $myCategory)" />
      </div>
    </div>
  </xsl:template>

  <xsl:template match="Row" mode="title">
    <div>
      <xsl:text>Title: </xsl:text>
      <xsl:value-of select="@Title" />
    </div>
  </xsl:template>
</xsl:stylesheet>

输出(我通常建议使用CSS格式化输出,而不是使用<br>):

<html>
   <body>
      <div class="language">
         <div>Below you can see all policies in English</div>
         <div>
            <div class="catecory">
               <div>Category: Category 1</div>
               <div>
                  <div>Title: Testitem</div>
                  <div>Title: Doc1</div>
               </div>
            </div>
         </div>
      </div>
      <div class="language">
         <div>Below you can see all policies in Nederlands (Dutch)</div>
         <div>
            <div class="catecory">
               <div>Category: Category 1</div>
               <div>
                  <div>Title: Policy3</div>
               </div>
            </div>
         </div>
      </div>
   </body>
</html>

主要更改是将子组键(语言+类别)移动到变量$myCategory中,这样可以在双重分组中选择正确的节点。

你的原始表达:

$thisLanguage[count(. | key('byCATEGORY', concat(@Language, '+', @Category))[1])= 1]

指的是谓词中的错误上下文(它指的是$thisLanguage,它没有@Language或@Category)。将concat(...)移出此表达式会生成正确的结果。

次要变化是在输出中添加一些结构,因此可以通过CSS更轻松地定位它。

还要注意输出方法和不同模板模式的使用。

常规提示:样式表中有许多名称空间声明。删除任何不在样式表中主动使用的内容。