在XSLT处理之后生成一系列位置

时间:2011-12-16 20:05:40

标签: javascript xslt

前言:我在XSLT中创建了一个包含子项的表(它是表格形式的树视图)。我处理手动隐藏/显示子节点的JS,但它很快变得一团糟,难以维护。我已经开始玩JQTreeTable

这是一个示例输入(这与JSFiddle链接匹配):http://pastebin.com/NQVHsy69

问题:JQTreeTable需要通过数组了解节点的关联方式。它应该是这样的:http://jsfiddle.net/vt7Xd/30/

如果你看一下JavaScript:

var map1 = [0,      1,      1,      1,      1,      1,      6,      1      ];
            ^ 5600  ^ 5601  ^ 5602  ^ 5603  ^ 5604  ^ 5605  ^ 5606  ^ 5607  

这些是位置/关系标识符。第一个元素是根(0),接下来的几个是第一行的子元素。然后第7行是第6行的孩子。

我需要在XSLT中生成这个数组。使用position()来获得正确的级别可以正常工作,但是如何保证在处理结束时生成这个数组,或者在处理过程中是否有办法附加到数组?这甚至可行吗?

2 个答案:

答案 0 :(得分:2)

@lwburk的答案很好,但它的速度是二次方(O(N ^ 2))。

这是一个简单的线性速度(O(N))解决方案

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common">
 <xsl:output method="text"/>

 <xsl:key name="kRowById" match="Row"
  use="ID"/>

 <xsl:variable name="vRows" select="/*/*"/>

 <xsl:variable name="vTopIndex" select="1"/>

 <xsl:template match="Row" mode="pass1">
  <Row pos="{position()}">
   <xsl:copy-of select="node()"/>
  </Row>
 </xsl:template>

 <xsl:variable name="vrtfPass1">
  <xsl:apply-templates select="/*/Row" mode="pass1"/>
 </xsl:variable>

 <xsl:variable name="vPass1" select=
  "ext:node-set($vrtfPass1)/*"/>

 <xsl:template match="/">
  var map1 = [ <xsl:text/>
  <xsl:apply-templates select="$vPass1"/>
  <xsl:text>];</xsl:text>
 </xsl:template>

 <xsl:template match="Row">
  <xsl:if test="position() > 1">, </xsl:if>
  <xsl:value-of select=
   "key('kRowById', MasterID)/@pos
   -
    (MasterID = ID)
   "/>
 </xsl:template>
</xsl:stylesheet>

应用于此XML文档(问题中没有提供内联的XML文档!!!):

<Rows>
    <Row>
        <ID>5600</ID>
        <MasterID>5600</MasterID>
        <Name>A Product</Name>
        <Owner>RyanB_Admin</Owner>
        <CompletionPercentage>1</CompletionPercentage>
    </Row>
    <Row>
        <ID>5601</ID>
        <MasterID>5600</MasterID>
        <Name>Requirements Gathering</Name>
        <Owner>RyanB_Admin</Owner>
        <CompletionPercentage>100</CompletionPercentage>
    </Row>
    <Row>
        <ID>5602</ID>
        <MasterID>5600</MasterID>
        <Name>Design</Name>
        <Owner>RyanB_Admin</Owner>
        <CompletionPercentage>0</CompletionPercentage>
    </Row>
    <Row>
        <ID>5603</ID>
        <MasterID>5600</MasterID>
        <Name>Development</Name>
        <Owner>RyanB_Admin</Owner>
        <CompletionPercentage>0</CompletionPercentage>
    </Row>
    <Row>
        <ID>5604</ID>
        <MasterID>5600</MasterID>
        <Name>Testing</Name>
        <Owner>RyanB_Admin</Owner>
        <CompletionPercentage>0</CompletionPercentage>
    </Row>
    <Row>
        <ID>5605</ID>
        <MasterID>5600</MasterID>
        <Name>Documentation</Name>
        <Owner>RyanB_Admin</Owner>
        <CompletionPercentage>0</CompletionPercentage>
    </Row>
    <Row>
        <ID>5606</ID>
        <MasterID>5605</MasterID>
        <Name>Special documentation</Name>
        <Owner>RyanB_Admin</Owner>
        <CompletionPercentage>0</CompletionPercentage>
    </Row>
    <Row>
        <ID>5607</ID>
        <MasterID>5600</MasterID>
        <Name>Implementation</Name>
        <Owner>RyanB_Admin</Owner>
        <CompletionPercentage>0</CompletionPercentage>
    </Row>
</Rows>

产生了想要的正确结果

  var map1 = [ 0, 1, 1, 1, 1, 1, 6, 1];

<强>解释

  1. 这是一个双程解决方案。在第一遍中,我们“按原样”复制所有元素,但为每个pos添加Row属性。此新属性的值是此Row在其兄弟Row元素中的相对位置。

  2. 在每个Row的第二遍中,我们得到它的主Row(使用一个非常快速(O(1))访问的键)然后我们输出这个主的值{ pos属性。

答案 1 :(得分:1)

以下样式表将每个Row与其前面的Row相关联MasterID

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="/">
        <xsl:text>var map1 = [</xsl:text>
        <xsl:apply-templates select="/*/Row"/>
        <xsl:text>];</xsl:text>
    </xsl:template>
    <xsl:template match="Row[ID=MasterID]">0</xsl:template>
    <xsl:template match="Row">
        <xsl:text>, </xsl:text>
        <xsl:value-of select="count(preceding-sibling::Row[
            ID=current()/MasterID]/preceding-sibling::Row) + 1."/>
    </xsl:template>
</xsl:stylesheet>

应用于此输入:

<Rows>
    <Row>
        <ID>5600</ID>
        <MasterID>5600</MasterID>
        <Name>A Product</Name>
        <Owner>RyanB_Admin</Owner>
        <CompletionPercentage>1</CompletionPercentage>
    </Row>
    <Row>
        <ID>5601</ID>
        <MasterID>5600</MasterID>
        <Name>Requirements Gathering</Name>
        <Owner>RyanB_Admin</Owner>
        <CompletionPercentage>100</CompletionPercentage>
    </Row>
    <Row>
        <ID>5602</ID>
        <MasterID>5600</MasterID>
        <Name>Design</Name>
        <Owner>RyanB_Admin</Owner>
        <CompletionPercentage>0</CompletionPercentage>
    </Row>
    <Row>
        <ID>5603</ID>
        <MasterID>5600</MasterID>
        <Name>Development</Name>
        <Owner>RyanB_Admin</Owner>
        <CompletionPercentage>0</CompletionPercentage>
    </Row>
    <Row>
        <ID>5604</ID>
        <MasterID>5600</MasterID>
        <Name>Testing</Name>
        <Owner>RyanB_Admin</Owner>
        <CompletionPercentage>0</CompletionPercentage>
    </Row>
    <Row>
        <ID>5605</ID>
        <MasterID>5600</MasterID>
        <Name>Documentation</Name>
        <Owner>RyanB_Admin</Owner>
        <CompletionPercentage>0</CompletionPercentage>
    </Row>
    <Row>
        <ID>5606</ID>
        <MasterID>5605</MasterID>
        <Name>Special documentation</Name>
        <Owner>RyanB_Admin</Owner>
        <CompletionPercentage>0</CompletionPercentage>
    </Row>
    <Row>
        <ID>5607</ID>
        <MasterID>5600</MasterID>
        <Name>Implementation</Name>
        <Owner>RyanB_Admin</Owner>
        <CompletionPercentage>0</CompletionPercentage>
    </Row>
</Rows>

产生以下输出:

var map1 = [0, 1, 1, 1, 1, 1, 6, 1];

请注意,这需要最直接的方法来查找每个Row元素的主文件在处理时,这可能在非常大的文档上表现不佳。