Сортированный для каждого цикла в XSLT не может ссылаться на узлы для запроса XPath вне цикла - PullRequest
0 голосов
/ 21 февраля 2019

Я пытаюсь перебрать набор узлов, чтобы создать меню из отдельных отсортированных значений.Все возможные значения известны, но какие и сколько включены в XML, неизвестно во время выполнения.Известный список время от времени меняется, поэтому включение полного списка потребовало бы контроля технического обслуживания, которого я бы предпочел избегать.

Текст ошибки: Требуемый тип элемента элемента контекста для родительской оси - это узел ();предоставленное значение имеет тип элемента xs: anyAtomicType .

Я использую XSLT 2.0 от Xerces, встроенного в Solr 7.6.

Мне кажется, я понимаю, почему, потому что я контекстуально на текстовое значениеи не на узле, но я не знаю, как обойти это.

Вот пример XML ...

<?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-преобразование с ошибками, вызывающими строки, комментируютсяout ...

<?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>

И, наконец, результат с заполнителями для недоступных данных ...

<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

1 Ответ

0 голосов
/ 21 февраля 2019

Один из способов обойти это - определить переменную верхнего уровня, содержащую весь документ, как в этот ответ :

...
<xsl:output method="html" indent="yes"/>
<xsl:variable name="mainDoc" select="/" />
...

Затем сослаться на нее в закомментированных переменных (Я также изменил предикат в count для подсчета нужных узлов):

Первый

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

и второй

<xsl:variable name="typeName" select="($mainDoc//doc[str[@name='type-abbrv']/text()=$typeAbbrv]/str[@name='type-name'])[1]" />
...