基于项目编号的XSLT树结构

时间:2014-01-20 01:58:02

标签: jquery xml xslt tree jstree

我的XSLT-Stylesheet有问题。我有一个包含多个程序集的XML文档。每个组件都有一个唯一的项目编号。程序集可以包含其他程序集作为位置,但XML文档具有如下平面结构:

<?xml version="1.0" encoding="ISO-8859-1"?>
<PartsCatalog Version="1.0">
<Description><![CDATA[asdsadasdadad       ]]></Description>
<Assembly Item="0000            " Plate="          " Class="                ">
<Description Lang=" DE"><![CDATA[Main assembly]]></Description>
<Description Lang=" EN"><![CDATA[Main assembly]]></Description>
<Description Lang=" FR"><![CDATA[Main assembly]]></Description>
<Description Lang=" IT"><![CDATA[Main assembly]]></Description>
<Description Lang=" RU"><![CDATA[Main assembly]]></Description>
<Position PositionNumber="  10" Item="9284424         " Plate="000020    " Class="                ">
    <Quantity Unit="st ">        1,0000</Quantity>
    <Serie From="          " To="          "></Serie>
    <Characteristic><![CDATA[                              ]]></Characteristic>
    <SparePartFlag><![CDATA[00]]></SparePartFlag>
    <Description Lang=" DE"><![CDATA[aaaaaa            ]]></Description>
    <Description Lang=" EN"><![CDATA[aaaaaa            ]]></Description>
    <Description Lang=" FR"><![CDATA[aaaaaa            ]]></Description>
    <Description Lang=" IT"><![CDATA[aaaaaa            ]]></Description>
    <Description Lang=" RU"><![CDATA[                              ]]></Description>
</Position>
<Position PositionNumber="  20" Item="9207826         " Plate="104300    " Class="                ">
    <Quantity Unit="st ">        1,0000</Quantity>
    <Serie From="          " To="          "></Serie>
    <Characteristic><![CDATA[10.00-20 PR16                 ]]></Characteristic>
    <SparePartFlag><![CDATA[00]]></SparePartFlag>
    <Description Lang=" DE"><![CDATA[8 GELAENDEREIFEN              ]]></Description>
    <Description Lang=" EN"><![CDATA[8 OFFROAD TIRES               ]]></Description>
    <Description Lang=" FR"><![CDATA[8 PNEUS TOUT-TERRAIN          ]]></Description>
    <Description Lang=" IT"><![CDATA[8 PNEUMATICI FUORI STRADA     ]]></Description>
    <Description Lang=" RU"><![CDATA[                              ]]></Description>
</Position>
<Position PositionNumber="  30" Item="9178702         " Plate="104280    " Class="                ">
    <Quantity Unit="st ">        1,0000</Quantity>
    <Serie From="          " To="          "></Serie>
    <Characteristic><![CDATA[MH 3                          ]]></Characteristic>
    <SparePartFlag><![CDATA[00]]></SparePartFlag>
    <Description Lang=" DE"><![CDATA[ZWISCHENRING                  ]]></Description>
    <Description Lang=" EN"><![CDATA[INTERMEDIATE RING             ]]></Description>
    <Description Lang=" FR"><![CDATA[ENTRETOISE                    ]]></Description>
    <Description Lang=" IT"><![CDATA[ANELLO DISTANZIATORE          ]]></Description>
    <Description Lang=" RU"><![CDATA[ÏÐÎÊËÀÄÎ×ÍÎÅ ÊÎËÜÖÎ           ]]></Description>
</Position>
<Assembly Item="9284424         " Plate="000020    " Class="11100301        ">
<Description Lang=" DE"><![CDATA[aaaaa            ]]></Description>
<Description Lang=" EN"><![CDATA[aaaaa            ]]></Description>
<Description Lang=" FR"><![CDATA[aaaaa            ]]></Description>
<Description Lang=" IT"><![CDATA[aaaaa            ]]></Description>
<Description Lang=" RU"><![CDATA[                              ]]></Description>
<Image PositionFrom="   0">187994</Image>
<Position PositionNumber=" 100" Item="9284426         " Plate="201000    " Class="110000          ">
    <Quantity Unit="st ">        1,0000</Quantity>
    <Serie From="          " To="          "></Serie>
    <Characteristic><![CDATA[                              ]]></Characteristic>
    <SparePartFlag><![CDATA[20]]></SparePartFlag>
    <Description Lang=" DE"><![CDATA[OBERWAGEN                     ]]></Description>
    <Description Lang=" EN"><![CDATA[UPPERCARRIAGE                 ]]></Description>
    <Description Lang=" FR"><![CDATA[TOURELLE                      ]]></Description>
    <Description Lang=" IT"><![CDATA[TORRETTA                      ]]></Description>
    <Description Lang=" RU"><![CDATA[ÏÎÂÎÐÎÒÍÀß ÏËÀÒÔÎÐÌÀ          ]]></Description>
</Position>
<Position PositionNumber=" 200" Item="9281013         " Plate="102000    " Class="110000          ">
    <Quantity Unit="st ">        1,0000</Quantity>
    <Serie From="          " To="          "></Serie>
    <Characteristic><![CDATA[                              ]]></Characteristic>
    <SparePartFlag><![CDATA[20]]></SparePartFlag>
    <Description Lang=" DE"><![CDATA[UNTERWAGEN 2PKT.              ]]></Description>
    <Description Lang=" EN"><![CDATA[UNDERCARRIAGE 2PTS.           ]]></Description>
    <Description Lang=" FR"><![CDATA[CHASSIS 2PTS.                 ]]></Description>
    <Description Lang=" IT"><![CDATA[CARRO 2STAB.                  ]]></Description>
    <Description Lang=" RU"><![CDATA[                              ]]></Description>
</Position>
</Assembly>

识别子装配的唯一方法是项目编号。 我想使用jsTree jquery插件将XML显示为树结构。 因此我需要一个像这样的HTML输出:

<div id="jsTree">
 <ul>
  <li>0001 | Main assembly
    <ul>
      <li>1111 | Sub assembly 1</li>
      <li>2222 | Sub assembly 2</li>
      <li>3333 | Sub assembly 3</li>
    </ul>
  </li>
 </ul>
</div>

到目前为止,我尝试使用与我的问题类似的许多问题的答案,但没有任何效果。谁能帮我?提前谢谢!

问候 B0R0H

3 个答案:

答案 0 :(得分:1)

您需要使用,以便每个程序集都可以(递归地)将模板应用于其组件:

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

<xsl:key name="kAssy" match="Assembly" use="@Item" />

<xsl:template match="/PartsCatalog">
<div id="jsTree">
    <ul>
        <xsl:apply-templates select="Assembly[Description='Main assembly']"/>
    </ul>
</div>
</xsl:template>

<xsl:template match="Assembly">
<li>
    <xsl:value-of select="@Item"/>
    <xsl:text> | </xsl:text>
    <xsl:value-of select="Description"/>
    <xsl:variable name="mySubs" select="key('kAssy', Position/@Item)" />
    <xsl:if test="$mySubs">
        <ul>
            <xsl:apply-templates select="$mySubs"/>
        </ul>
    </xsl:if>
</li>
</xsl:template>

</xsl:stylesheet> 

答案 1 :(得分:0)

基本答案是你需要以正常的方式使用xsl:apply-templates通过数据进行自上而下的递归下降,但有一个例外:而不是处理XML树中节点的物理子节点,你需要处理它的逻辑孩子。所以不要写

<xsl:apply-templates select="child::node()"/>
像往常一样,你写了

<xsl:apply-templates select="//Assembly[@Item = current()/Position/@Item]"/>

然后下一个阶段就是你可以使用密钥来优化它,如michael.hor257k所描述的(如果你使用像Saxon-EE这样自动进行优化的处理器,则不需要)。

答案 2 :(得分:0)

感谢您的帮助! :)刚刚找到问题的解决方案。我会将其发布给其他(也许)类似问题的人。这个对我有用:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="html" encoding="utf-8"/>
<xsl:variable name="lang-all" select="distinct-values(//Description/@Lang)"/>
<xsl:template match="/">
    <xsl:variable name="doc" select="."/>
    <xsl:for-each select="$lang-all">
        <xsl:variable name="lang" select="."/>
        <xsl:for-each select="$doc">
            <xsl:variable name="filename_index" select="concat('output/',$lang,'/','index','.html')"/>
            <xsl:variable name="jstree">
                <xsl:call-template name="build-list">
                    <xsl:with-param name="lang" select="$lang" />
                    <xsl:with-param name="node" select="PartsCatalog/Assembly[1]" />
                </xsl:call-template>
            </xsl:variable>
            <xsl:value-of select="$filename_index"/>
            <xsl:result-document href="{$filename_index}">
                <html>
                    <head>
                        <meta charset="utf-8"/>
                        <title>ETK</title>
                        <script src="../0jquery/jquery-ui-1.10.3/jquery-1.9.1.js"/>
                        <script src="../0jquery/jquery-ui-1.10.3/ui/jquery-ui.js"/>
                        <script src="../0dropdown/jquery.easydropdown.min.js"/>
                        <script src="../0jstree/dist/jstree.min.js"/>
                        <link rel="stylesheet" href="../0jquery/jquery-ui-themes-1.10.3/themes/smoothness/jquery-ui.css"/>
                        <link rel="stylesheet" href="../0jstree/dist/themes/default/style.min.css" />
                        <link rel="stylesheet" href="../0dropdown/themes/easydropdown.css" type="text/css"/>
                        <link rel="stylesheet" href="../0css/style.css"  type="text/css"/>
                    </head>
                    <body>
                        <div class="head">
                            <div class="innertube_head">
                                <h1>ETK</h1>
                            </div>
                        </div>
                        <div class="left">
                            <div class="jstree_header">
                                <xsl:value-of select="PartsCatalog/Description"/>
                            </div>
                            <div class="innertube_left" id="jstree">
                                <xsl:copy-of select="$jstree" />
                            </div>
                        </div>
                        <div class="center">
                            <div class="center_top"/>
                            <div class="center_bottom"/>
                        </div>
                        <div class="right">
                            <div class="3d_frame"></div>
                            <div class="innertube_right">
                                    <select id="countries" class="dropdown">
                                        <option value="#">Change language</option>
                                        <option value="../{$lang-all[1]}/index.html">german</option>
                                        <option value="../{$lang-all[2]}/index.html">english</option>
                                        <option value="../{$lang-all[3]}/index.html">french</option>
                                        <option value="../{$lang-all[4]}/index.html">italian</option>
                                        <option value="../{$lang-all[5]}/index.html">russian</option>
                                    </select>
                                    <script>
                                        $('#countries').bind('change', function () {

                                            var url = $(this).val();

                                            if (url != '') {
                                                window.location = url;
                                            }
                                            return false;
                                        });
                                    </script>
                            </div>
                        </div>
                        <script>
                          $(function () {
                            // 6 create an instance when the DOM is ready
                            $('#jstree').jstree();

                            // 7 bind to events triggered on the tree
                            $('#jstree').on("changed.jstree", function (e, data) {
                              console.log(data.selected);
                            });

                            // 8 interact with the tree - either way is OK
                            $('button').on('click', function () {
                              $('#jstree').jstree(true).select_node('child_node_1');
                              $('#jstree').jstree('select_node', 'child_node_1');
                              $.jstree.reference('#jstree').select_node('child_node_1');
                            });
                          });
                        </script>
                    </body>
                </html>
            </xsl:result-document>
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>
<xsl:template match="Assembly">
    <xsl:apply-templates select="Position"/>
</xsl:template>
<xsl:template match="Position">
    <xsl:param name="lang"/>
    <TR>
        <TD>
            <xsl:value-of select="normalize-space(@PositionNumber)"/>
        </TD>
        <TD>
            <xsl:value-of select="normalize-space(Description[@Lang=$lang])"/>
        </TD>
        <TD>
            <xsl:value-of select="normalize-space(@Item)"/>
        </TD>
        <TD>
            <xsl:value-of select="normalize-space(Quantity)"/>
        </TD>
        <TD>
            <xsl:value-of select="normalize-space(Quantity/@Unit)"/>
        </TD>
    </TR>
</xsl:template>
<xsl:template name="build-list">
<xsl:param name="node"></xsl:param>
<xsl:param name="lang"></xsl:param>
    <ul>
        <xsl:for-each select="$node/Position">
            <xsl:variable name="item" select="@Item" />
            <xsl:if test="count(//Assembly[@Item = $item]) != 0">
                <li>
                    <xsl:value-of select="normalize-space(@Item)"/> | <xsl:value-of select="normalize-space(Description[@Lang=$lang])"/>
                    <xsl:call-template name="build-list">
                        <xsl:with-param name="node" select="//Assembly[@Item = $item]" />
                        <xsl:with-param name="lang" select="$lang" />
                    </xsl:call-template>
                </li>
            </xsl:if>
            <xsl:if test="count(//Assembly[@Item = $item]) = 0">
                <li><xsl:value-of select="normalize-space(@Item)"/> | <xsl:value-of select="normalize-space(Description[@Lang=$lang])"/></li>
            </xsl:if>
        </xsl:for-each>
    </ul>
</xsl:template>
</xsl:stylesheet>