首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >排序- XSLT中的每个循环不能将节点引用到循环外的XPath查询。

排序- XSLT中的每个循环不能将节点引用到循环外的XPath查询。
EN

Stack Overflow用户
提问于 2019-02-21 16:07:31
回答 2查看 227关注 0票数 0

我正在尝试遍历一组节点,以构建一个具有不同排序值的菜单。所有可能的值都是已知的,但是在运行时不知道XML中包含了哪些值和多少值。已知的列表不时发生变化,因此,包括完整的列表将需要维护控制,我宁愿避免。

错误文本是必需的上下文项类型,父轴是节点();所提供的值具有项目类型xs:anyAtomicType

我正在使用嵌入在Solr 7.6中的Xerces的XSLT2.0。

我想我理解为什么,因为我在上下文中是一个文本值,而不是一个节点,但我不知道如何绕过它。

这里有一个XML示例..。

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<response>

<result name="response" numFound="25" start="0">
  <doc>
    <str name="id">REF-50102</str>
    <str name="type-name">Reference</str>
    <str name="type-abbrv">REF</str>
  </doc>
  <doc>
    <str name="id">REF-50222</str>
    <str name="type-name">Reference</str>
    <str name="type-abbrv">REF</str>
  </doc>
  <doc>
    <str name="id">REF-50245</str>
    <str name="type-name">Reference</str>
    <str name="type-abbrv">REF</str>
  </doc>
  <doc>
    <str name="id">REF-50029</str>
    <str name="type-name">Reference</str>
    <str name="type-abbrv">REF</str>
  </doc>
  <doc>
    <str name="id">SUB-4</str>
    <str name="type-name">Subsystem</str>
    <str name="type-abbrv">SUB</str>
    <str name="system-name">AC-9</str>
  </doc>
  <doc>
    <str name="id">STK-80</str>
    <str name="type-name">Stack</str>
    <str name="type-abbrv">STK</str>
    <str name="system-name">AC-9</str>
  </doc>
  <doc>
    <str name="id">STK-61</str>
    <str name="type-name">Stack</str>
    <str name="type-abbrv">STK</str>
    <str name="system-name">AC-9</str>
  </doc>
  <doc>
    <str name="id">FLM-50025</str>
    <str name="type-name">Flavor</str>
    <str name="type-abbrv">FLM</str>
    <str name="system-name">AC-9</str>
  </doc>
  <doc>
    <str name="id">FLM-50108</str>
    <str name="type-name">Flavor</str>
    <str name="type-abbrv">FLM</str>
    <str name="system-name">AC-9</str>
  </doc>
  <doc>
    <str name="id">FLM-50109</str>
    <str name="type-name">Flavor</str>
    <str name="type-abbrv">FLM</str>
    <str name="system-name">AC-9</str>
  </doc>
  <doc>
    <str name="id">PFP-50101</str>
    <str name="type-name">Prefabricated</str>
    <str name="type-abbrv">PFP</str>
    <str name="system-name">AC-9</str>
  </doc>
  <doc>
    <str name="id">PFP-50103</str>
    <str name="type-name">Prefabricated</str>
    <str name="type-abbrv">PFP</str>
    <str name="system-name">AC-9</str>
  </doc>
  <doc>
    <str name="id">DSG-50163</str>
    <str name="type-name">Design Drawing</str>
    <str name="type-abbrv">DSG</str>
    <str name="system-name">AB-4</str>
  </doc>
  <doc>
    <str name="id">DSG-50164</str>
    <str name="type-name">Design Drawing</str>
    <str name="type-abbrv">DSG</str>
    <str name="system-name">AC-8</str>
  </doc>
  <doc>
    <str name="id">DSG-50162</str>
    <str name="type-name">Design Drawing</str>
    <str name="type-abbrv">DSG</str>
    <str name="system-name">AB-4</str>
  </doc>
  <doc>
    <str name="id">PXS-81</str>
    <str name="type-name">Production Assembly</str>
    <str name="type-abbrv">PXS</str>
    <str name="system-name">AC-9</str>
  </doc>
  <doc>
    <str name="id">PXS-83</str>
    <str name="type-name">Production Assembly</str>
    <str name="type-abbrv">PXS</str>
    <str name="system-name">AC-9</str>
  </doc>
  <doc>
    <str name="id">PXS-82</str>
    <str name="type-name">Production Assembly</str>
    <str name="type-abbrv">PXS</str>
    <str name="system-name">AC-9</str>
  </doc>
  <doc>
    <str name="id">DWG-42</str>
    <str name="type-name">Drawing</str>
    <str name="type-abbrv">DWG</str>
    <str name="system-name">AC-9</str>
  </doc>
</result>
</response>

将引起行错误的XSL变换注释掉.

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    <!-- =========================================================================================== -->
    <xsl:output method="html" indent="yes"/>
    <!-- =========================================================================================== -->
    <xsl:template match="/response">
        <html>
            <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
            </head>
            <body>
                <xsl:comment>Working if I know the list, but I do not.</xsl:comment>
                <xsl:apply-templates select="result" mode="countKnownList"/>
                <hr/>
                <xsl:comment>Finds list dynamically, but can not get name or count.</xsl:comment>
                <xsl:apply-templates select="result" mode="countUnknownList"/>
            </body>
        </html>
    </xsl:template>
    <!-- =========================================================================================== -->
    <xsl:template name="listElementUnknownList">
        <xsl:param name="abbrv"/>
        <xsl:param name="name"/>
<!-- What I have tried unsuccessfully.
        <xsl:variable name="quantity"><xsl:value-of select="count(//doc/str[@name='type-abbrv']/text()='$abbrv')"/></xsl:variable>
 -->
        <xsl:variable name="quantity">#</xsl:variable>
        <li><label>
            <xsl:element name="input">
                <xsl:attribute name="id"><xsl:value-of select="$abbrv"/></xsl:attribute>
                <xsl:attribute name="type">checkbox</xsl:attribute>
                <xsl:attribute name="checked">true</xsl:attribute>
                <xsl:attribute name="onclick">toggleRows('<xsl:value-of select="$abbrv"/>');</xsl:attribute>
            </xsl:element><xsl:value-of select="$name"/>(<xsl:value-of select="$quantity" />)</label></li>
    </xsl:template>
    <!-- =========================================================================================== -->
     <xsl:template match="result" mode="countUnknownList">
        <dl>
            <dt>Type (<xsl:value-of select="count(doc)" />)</dt>
            <dd>
                <ul>
                    <xsl:for-each select="distinct-values(doc/str[@name='type-abbrv'])">
                        <xsl:sort select="."/>
                        <xsl:variable name="typeAbbrv"><xsl:value-of select="."/></xsl:variable>
<!--  What I have tried unsuccessfully.
                        <xsl:variable name="typeName"><xsl:value-of select="../str[@name='type-name']"/></xsl:variable>
 -->
                        <xsl:variable name="typeName"><xsl:value-of select="$typeAbbrv"/>-name</xsl:variable>
                        <xsl:call-template name="listElementUnknownList">
                            <xsl:with-param name="abbrv"><xsl:value-of select="$typeAbbrv"/></xsl:with-param>
                            <xsl:with-param name="name"><xsl:value-of select="$typeName"/></xsl:with-param>
                        </xsl:call-template>
                    </xsl:for-each>
                 </ul>
            </dd>
            <dt>System (<xsl:value-of select="count(doc)" />)</dt>
            <dd>
                <ul>
                    <xsl:for-each select="distinct-values(doc/str[@name='system-name']/text())">
                        <xsl:sort select="."/>
                        <xsl:variable name="sysName"><xsl:value-of select="."/></xsl:variable>
                        <xsl:call-template name="listElementUnknownList">
                            <xsl:with-param name="abbrv"><xsl:value-of select="$sysName"/></xsl:with-param>
                            <xsl:with-param name="name"><xsl:value-of select="$sysName"/></xsl:with-param>
                        </xsl:call-template>
                    </xsl:for-each>
                    <xsl:call-template name="listElementUnknownList">
                        <xsl:with-param name="abbrv">None</xsl:with-param>
                        <xsl:with-param name="name">None</xsl:with-param>
                    </xsl:call-template>
                </ul>
            </dd>
        </dl>
    </xsl:template>
    <!-- =========================================================================================== -->
    <xsl:template name="listElementKnownList">
        <xsl:param name="abbrv"/>
        <xsl:param name="name"/>
        <xsl:param name="quantity"/>
        <li><label>
            <xsl:element name="input">
                <xsl:attribute name="id"><xsl:value-of select="$abbrv"/></xsl:attribute>
                <xsl:attribute name="type">checkbox</xsl:attribute>
                <xsl:attribute name="checked">true</xsl:attribute>
                <xsl:attribute name="onclick">toggleRows('<xsl:value-of select="$abbrv"/>');</xsl:attribute>
            </xsl:element><xsl:value-of select="$name"/>(<xsl:value-of select="$quantity" />)</label></li>
    </xsl:template>
    <!-- =========================================================================================== -->
     <xsl:template match="result" mode="countKnownList">
        <dl>
            <dt>Type (<xsl:value-of select="count(doc)" />)</dt>
            <dd>
                <ul>
                    <xsl:call-template name="listElementKnownList">
                        <xsl:with-param name="abbrv">DSG</xsl:with-param>
                        <xsl:with-param name="name">Design Drawing</xsl:with-param>
                        <xsl:with-param name="quantity"><xsl:value-of select="count(doc[str[@name='type-abbrv']/text()='DSG'])"/></xsl:with-param>
                    </xsl:call-template>
                    <xsl:call-template name="listElementKnownList">
                        <xsl:with-param name="abbrv">FLM</xsl:with-param>
                        <xsl:with-param name="name">Flavor</xsl:with-param>
                        <xsl:with-param name="quantity"><xsl:value-of select="count(doc[str[@name='type-abbrv']/text()='FLM'])"/></xsl:with-param>
                    </xsl:call-template>
                    <xsl:call-template name="listElementKnownList">
                        <xsl:with-param name="abbrv">STK</xsl:with-param>
                        <xsl:with-param name="name">Stack</xsl:with-param>
                        <xsl:with-param name="quantity"><xsl:value-of select="count(doc[str[@name='type-abbrv']/text()='STK'])"/></xsl:with-param>
                    </xsl:call-template>
                    <!-- etc -->
                </ul>
            </dd>
        </dl>
    </xsl:template>
    <!-- =========================================================================================== -->
</xsl:stylesheet>

最后,对于不可用数据的占位符的结果.

代码语言:javascript
复制
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   </head>
   <body>
      <!--Working if I know the list, but I do not.-->
      <dl>
         <dt>Type (19)</dt>
         <dd>
            <ul>
               <li><label><input id="DSG" type="checkbox" checked="true" onclick="toggleRows('DSG');">Design Drawing(3)</label></li>
               <li><label><input id="FLM" type="checkbox" checked="true" onclick="toggleRows('FLM');">Flavor(3)</label></li>
               <li><label><input id="STK" type="checkbox" checked="true" onclick="toggleRows('STK');">Stack(2)</label></li>
            </ul>
         </dd>
      </dl>
      <hr>
      <!--Finds list dynamically, but can not get name or count.-->
      <dl>
         <dt>Type (19)</dt>
         <dd>
            <ul>
               <li><label><input id="DSG" type="checkbox" checked="true" onclick="toggleRows('DSG');">DSG-name(#)</label></li>
               <li><label><input id="DWG" type="checkbox" checked="true" onclick="toggleRows('DWG');">DWG-name(#)</label></li>
               <li><label><input id="FLM" type="checkbox" checked="true" onclick="toggleRows('FLM');">FLM-name(#)</label></li>
               <li><label><input id="PFP" type="checkbox" checked="true" onclick="toggleRows('PFP');">PFP-name(#)</label></li>
               <li><label><input id="PXS" type="checkbox" checked="true" onclick="toggleRows('PXS');">PXS-name(#)</label></li>
               <li><label><input id="REF" type="checkbox" checked="true" onclick="toggleRows('REF');">REF-name(#)</label></li>
               <li><label><input id="STK" type="checkbox" checked="true" onclick="toggleRows('STK');">STK-name(#)</label></li>
               <li><label><input id="SUB" type="checkbox" checked="true" onclick="toggleRows('SUB');">SUB-name(#)</label></li>
            </ul>
         </dd>
         <dt>System (19)</dt>
         <dd>
            <ul>
               <li><label><input id="AB-4" type="checkbox" checked="true" onclick="toggleRows('AB-4');">AB-4(#)</label></li>
               <li><label><input id="AC-8" type="checkbox" checked="true" onclick="toggleRows('AC-8');">AC-8(#)</label></li>
               <li><label><input id="AC-9" type="checkbox" checked="true" onclick="toggleRows('AC-9');">AC-9(#)</label></li>
               <li><label><input id="None" type="checkbox" checked="true" onclick="toggleRows('None');">None(#)</label></li>
            </ul>
         </dd>
      </dl>
   </body>
</html
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-02-24 19:17:15

这个变量解决了你的问题,但是如果你只使用xsl:for-each-group,你就不会有它了。

代码语言:javascript
复制
   <xsl:for-each-group select="doc" group-by="str[@name='type-abbrv']">
                    <xsl:sort select="current-grouping-key()"/>
                    <xsl:variable name="typeAbbrv" select="current-grouping-key()"/>

                    <xsl:variable name="typeName" select="str[@name='type-name']"/>

                    <xsl:variable name="typeName"><xsl:value-of select="$typeAbbrv"/>-name</xsl:variable>
                    <xsl:call-template name="listElementUnknownList">
                        <xsl:with-param name="abbrv"><xsl:value-of select="$typeAbbrv"/></xsl:with-param>
                        <xsl:with-param name="name"><xsl:value-of select="$typeName"/></xsl:with-param>
                    </xsl:call-template>
   </xsl:for-each-group>

当然可以缩短为

代码语言:javascript
复制
   <xsl:for-each-group select="doc" group-by="str[@name='type-abbrv']">
                    <xsl:sort select="current-grouping-key()"/>
                    <xsl:call-template name="listElementUnknownList">
                        <xsl:with-param name="abbrv" select="current-grouping-key()"/>
                        <xsl:with-param name="name" select="concat(str[@name='type-name'], '-name')"/>
                    </xsl:call-template>
   </xsl:for-each-group>

所以我认为分组是你真正想要的,我试着把它的一部分实现为

代码语言:javascript
复制
 <xsl:template match="result" mode="countUnknownList">
    <dl>
        <dt>Type (<xsl:value-of select="count(doc)" />)</dt>
        <dd>
            <ul>
               <xsl:for-each-group select="doc" group-by="str[@name='type-abbrv']">
                    <xsl:sort select="current-grouping-key()"/>
                    <li>
                       <label>
                           <input id="{current-grouping-key()}"
                                  type="checkbox"
                                  checked="checked"
                                  onclick="toggleRows('{current-grouping-key()}');"/>
                            <xsl:value-of select="concat(str[@name='type-name'], '(', count(current-group()), ')')"/>

                       </label> 
                    </li>
               </xsl:for-each-group>
             </ul>
        </dd>
        <dt>System (<xsl:value-of select="count(doc)" />)</dt>
        <dd>
            <ul>
               <xsl:for-each-group select="doc" group-by="str[@name='system-name']">
                    <xsl:sort select="current-grouping-key()"/>
                    <li>
                       <label>
                           <input id="{current-grouping-key()}"
                                  type="checkbox"
                                  checked="checked"
                                  onclick="toggleRows('{current-grouping-key()}');"/>
                            <xsl:value-of select="concat(current-grouping-key(), '(', count(current-group()), ')')"/>

                       </label> 
                    </li>
               </xsl:for-each-group>                    
            </ul>
        </dd>
    </dl>
</xsl:template>

https://xsltfiddle.liberty-development.net/gWvjQf4,您的示例的结果只有一个列表

代码语言:javascript
复制
        <ul>
           <li><label><input id="DSG" type="checkbox" checked onclick="toggleRows('DSG');">Design Drawing(3)</label></li>
           <li><label><input id="DWG" type="checkbox" checked onclick="toggleRows('DWG');">Drawing(1)</label></li>
           <li><label><input id="FLM" type="checkbox" checked onclick="toggleRows('FLM');">Flavor(3)</label></li>
           <li><label><input id="PFP" type="checkbox" checked onclick="toggleRows('PFP');">Prefabricated(2)</label></li>
           <li><label><input id="PXS" type="checkbox" checked onclick="toggleRows('PXS');">Production Assembly(3)</label></li>
           <li><label><input id="REF" type="checkbox" checked onclick="toggleRows('REF');">Reference(4)</label></li>
           <li><label><input id="STK" type="checkbox" checked onclick="toggleRows('STK');">Stack(2)</label></li>
           <li><label><input id="SUB" type="checkbox" checked onclick="toggleRows('SUB');">Subsystem(1)</label></li>
        </ul>

第二个

代码语言:javascript
复制
        <ul>
           <li><label><input id="AB-4" type="checkbox" checked onclick="toggleRows('AB-4');">AB-4(2)</label></li>
           <li><label><input id="AC-8" type="checkbox" checked onclick="toggleRows('AC-8');">AC-8(1)</label></li>
           <li><label><input id="AC-9" type="checkbox" checked onclick="toggleRows('AC-9');">AC-9(12)</label></li>
        </ul>

希望我已经掌握了原始代码的意图。

票数 1
EN

Stack Overflow用户

发布于 2019-02-21 17:51:14

避免这种情况的一种方法是定义一个包含整个文档的顶级变量,如在this answer中。

代码语言:javascript
复制
...
<xsl:output method="html" indent="yes"/>
<xsl:variable name="mainDoc" select="/" />
...

然后在注释掉的变量中引用它(我还更改了count中的谓词以计数所需的节点):

第一个

代码语言:javascript
复制
<xsl:variable name="quantity" select="count($mainDoc/response/result/doc/str[@name='type-abbrv' and text()=$abbrv])"/>

第二个

代码语言:javascript
复制
<xsl:variable name="typeName" select="($mainDoc//doc[str[@name='type-abbrv']/text()=$typeAbbrv]/str[@name='type-name'])[1]" />
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54811433

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档