首页 > 解决方案 > XSLT - 在 for-each 中更改 XPATH

问题描述

我在这里的第一条消息,我希望我能做对!欢迎任何帮助或建设性帮助(我是初学者)!我有一个产品可以有 2 个不同的名称 + 一些其他属性。我想为每个可能的主要名称和次要名称排上一排。

我调用了一个模板来显示主要名称,另一个调用产品的属性,没有问题,因为节点处于相同的“级别”。

然后我想调用第二个模板在同一行显示每个产品可能的每个第二个名称,然后调用属性模板,问题是我不能在“for-each”函数中回到父节点一次.

XSLT:

    <?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="SOF.xsl" ?>

<root>
    <intrants>
        <CCCs>
            <PPP>
                <nbID>01</nbID>
                <product-name>MainNameA</product-name>
                <int-composition>
                    <act-subs>
                        <act-sub>
                            <substance ref-type="substance" ref-id="00000000000000000001">subA</substance>
                            <variant>
                                <name>substanceA</name>
                            </variant>
                            <AS-concentration unite-id="10000000000000000001" unite="g/L">123.0</AS-concentration>
                        </act-sub>
                    </act-subs>
                </int-composition>
            </PPP>
            <PPP>
                <nbID>02</nbID>
                <product-name>MainNameB</product-name>
                <others-names> </others-names>
                <int-composition>
                    <act-subs>
                        <act-sub>
                            <substance ref-type="substance" ref-id="00000000000000000001">subA</substance>
                            <variant>
                                <name>substanceA</name>
                            </variant>
                            <AS-concentration unite-id="10000000000000000001" unite="g/L">123.0</AS-concentration>
                        </act-sub>
                    </act-subs>
                </int-composition>
            </PPP>
            <PPP>
                <nbID>03</nbID>
                <product-name>MainNameC</product-name>
                <others-names>
                    <other-name>
                        <type-name ref-type="type-name" ref-id="20150522093431975033" lib-court="SEC">Second name</type-name>
                        <name>SecondNameC</name>
                    </other-name>
                </others-names>
                <int-composition>
                    <act-subs>
                        <act-sub>
                            <substance ref-type="substance" ref-id="00000000000000000001">subA</substance>
                            <variant>
                                <name>substanceA</name>
                            </variant>
                            <AS-concentration unite-id="10000000000000000001" unite="g/L">123.0</AS-concentration>
                        </act-sub>
                    </act-subs>
                </int-composition>
            </PPP>
            <PPP>
                <nbID>04</nbID>
                <product-name>MainNameD</product-name>
                <others-names>
                    <other-name>
                        <type-name ref-type="type-name" ref-id="20150522093431975033" lib-court="SEC">Second name</type-name>
                        <name>SecondName1D</name>
                    </other-name>
                    <other-name>
                        <type-name ref-type="type-name" ref-id="20150522093431975033" lib-court="SEC">Second name</type-name>
                        <name>SecondName2D</name>
                    </other-name>
                </others-names>
                <int-composition>
                    <act-subs>
                        <act-sub>
                            <substance ref-type="substance" ref-id="00000000000000000001">subA</substance>
                            <variant>
                                <name>substanceA</name>
                            </variant>
                            <AS-concentration unite-id="10000000000000000001" unite="g/L">123.0</AS-concentration>
                        </act-sub>
                        <act-sub>
                            <substance ref-type="substance" ref-id="00000000000000000002">subB</substance>
                            <variant>
                                <name>substanceB</name>
                            </variant>
                            <AS-concentration unite-id="10000000000000000001" unite="g/kg">456.0</AS-concentration>
                        </act-sub>
                        <act-sub>
                            <substance ref-type="substance" ref-id="00000000000000000003">subC</substance>
                            <variant>
                                <name>substanceC</name>
                            </variant>
                            <AS-concentration unite-id="10000000000000000001" unite="%/L">678.0</AS-concentration>
                        </act-sub>
                    </act-subs>
                </int-composition>
            </PPP>
        </CCCs>
    </intrants>
</root>

XLM:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/">
        <html>
            <head>
                <title>Rep</title>
            </head>
            <body>
                <table style="width:100%">

                    <tr>
                        <th>Name</th>
                        <th>ID</th>
                        <th>Composition</th>
                    </tr>

                    <xsl:for-each select="root/intrants/CCCs/PPP">
                        <tr>
                            <xsl:call-template name="displayMN">
                            <xsl:with-param name="MN" select="." />
                        </xsl:call-template>
                        </tr>
                    </xsl:for-each>

                    <xsl:for-each select="/root/intrants/CCCs/PPP">
                        <xsl:if test="count(others-names/other-name) &gt; 0">
                            <xsl:for-each select="others-names/other-name/name">
                                <tr>
                                        <xsl:call-template name="displaySN">
                                            <xsl:with-param name="SN" select="/root/intrants/CCCs/PPP"/>
                                        </xsl:call-template>
                                </tr>
                            </xsl:for-each>
                        </xsl:if>
                    </xsl:for-each>

                </table>
            </body>
        </html>
    </xsl:template>

    <!-- Main Product -->

    <xsl:template name="displayMN">
        <xsl:param name="MN"/>
        <td>
            <xsl:call-template name="displayMainName">
                <xsl:with-param name="name" select="product-name"/>
            </xsl:call-template>
        </td>

        <xsl:call-template name="displayCore">
            <xsl:with-param name="Produit" select="."/>
        </xsl:call-template>

    </xsl:template>

    <!-- Second Product -->

    <xsl:template name="displaySN">
        <xsl:param name="SN"/>
        <td>
            <xsl:call-template name="displaySecondName">
                <xsl:with-param name="name" select="."/>
            </xsl:call-template>
        </td>

        <xsl:call-template name="displayCore">
            <xsl:with-param name="Produit" select="."/>
        </xsl:call-template>

    </xsl:template>

    <!-- Core -->
    <xsl:template name="displayCore">
        <xsl:param name="Produit"/>

        <td>
            <xsl:call-template name="displaynbID">
                <xsl:with-param name="nbID" select="nbID"/>
            </xsl:call-template>
        </td>

        <td>
            <xsl:call-template name="displayCompositionEN">
                <xsl:with-param name="Composition" select="."/>
            </xsl:call-template>
        </td>

    </xsl:template>

    <!-- Main Name -->

    <xsl:template name="displayMainName">
        <xsl:param name="name"/>
        <xsl:value-of select="$name"/>
    </xsl:template>

    <!-- Second Name -->

    <xsl:template name="displaySecondName">
        <xsl:param name="name"/>
        <xsl:value-of select="$name"/>
    </xsl:template>


    <!-- IDnb -->

    <xsl:template name="displaynbID">
        <xsl:param name="nbID"/>
        <xsl:value-of select="$nbID"/>
    </xsl:template>


    <!-- Composition EN -->

    <xsl:template name="displayCompositionEN">
        <xsl:param name="Composition"/>
        <xsl:for-each select="int-composition/act-subs/act-sub">
            <xsl:call-template name="displaySubstanceEN">
                <xsl:with-param name="AS" select="substance"/>
                <xsl:with-param name="SACc" select="AS-concentration"/>
            </xsl:call-template>
            <xsl:if test="position() != last()">
                <xsl:text> + </xsl:text>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>

    <!-- Substance EN-->

    <xsl:template name="displaySubstanceEN">
        <xsl:param name="AS"/>
        <xsl:param name="SACc"/>
        <xsl:value-of select="$AS"/>&#160;<xsl:value-of select="$SACc"/>&#160;<xsl:value-of select="$SACc/@unite"/>
    </xsl:template>

</xsl:stylesheet>

正如您在生成的转换中看到的那样,我无法返回属性信息:

结果

标签: xmlxslt

解决方案


我假设例如在包含SecondNameC的行中,在其余列中应该显示与MainNameC相同的值,即03subA 123.0 g/L

下面的脚本完成了这项工作:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" doctype-public="-//W3C//DTD XHTML 1.1//EN"
    doctype-system= "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"/>

  <xsl:template match="/">
    <html>
      <head><title>Rep</title></head>
      <body>
        <table style="width:80%" border="1">
          <tr><th>Name</th><th>ID</th><th>Composition</th></tr>
          <xsl:for-each select="root/intrants/CCCs/PPP">
            <tr>
              <xsl:call-template name="displayMN">
                <xsl:with-param name="MN" select="." />
              </xsl:call-template>
            </tr>
          </xsl:for-each>
          <xsl:for-each select="root/intrants/CCCs/PPP">
            <xsl:variable name="MN" select="."/>
            <xsl:if test="count(others-names/other-name) &gt; 0">
              <xsl:for-each select="others-names/other-name/name">
                <tr>
                  <xsl:call-template name="displaySN">
                    <xsl:with-param name="MN" select="$MN"/>
                  </xsl:call-template>
                </tr>
              </xsl:for-each>
            </xsl:if>
          </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>

  <!-- Main Product -->
  <xsl:template name="displayMN">
    <xsl:param name="MN"/>
    <td>
      <xsl:call-template name="displayMainName">
        <xsl:with-param name="name" select="product-name"/>
      </xsl:call-template>
    </td>
    <xsl:call-template name="displayCore">
      <xsl:with-param name="Produit" select="."/>
    </xsl:call-template>
  </xsl:template>

  <!-- Second Product -->
  <xsl:template name="displaySN">
    <xsl:param name="MN"/>
    <td>
      <xsl:call-template name="displaySecondName">
        <xsl:with-param name="name" select="."/>
      </xsl:call-template>
    </td>
    <xsl:call-template name="displayCore">
      <xsl:with-param name="Produit" select="$MN"/>
    </xsl:call-template>
  </xsl:template>

  <!-- Core -->
  <xsl:template name="displayCore">
    <xsl:param name="Produit"/>
    <td>
      <xsl:call-template name="displaynbID">
        <xsl:with-param name="nbID" select="$Produit/nbID"/>
      </xsl:call-template>
    </td>
    <td>
      <xsl:call-template name="displayCompositionEN">
        <xsl:with-param name="Composition" select="$Produit"/>
      </xsl:call-template>
    </td>
  </xsl:template>

  <!-- Main Name -->
  <xsl:template name="displayMainName">
    <xsl:param name="name"/>
    <xsl:value-of select="$name"/>
  </xsl:template>

  <!-- Second Name -->
  <xsl:template name="displaySecondName">
    <xsl:param name="name"/>
    <xsl:value-of select="$name"/>
  </xsl:template>

  <!-- IDnb -->
  <xsl:template name="displaynbID">
    <xsl:param name="nbID"/>
    <xsl:value-of select="$nbID"/>
  </xsl:template>

  <!-- Composition EN -->
  <xsl:template name="displayCompositionEN">
    <xsl:param name="Composition"/>
    <xsl:for-each select="$Composition/int-composition/act-subs/act-sub">
      <xsl:call-template name="displaySubstanceEN">
        <xsl:with-param name="AS" select="substance"/>
        <xsl:with-param name="SACc" select="AS-concentration"/>
      </xsl:call-template>
      <xsl:if test="position() != last()">
        <xsl:text> + </xsl:text>
  </xsl:if>
    </xsl:for-each>
  </xsl:template>

  <!-- Substance EN-->
  <xsl:template name="displaySubstanceEN">
    <xsl:param name="AS"/>
    <xsl:param name="SACc"/>
    <xsl:value-of select="$AS"/>&#160;<xsl:value-of select="$SACc"/>&#160;<xsl:value-of select="$SACc/@unite"/>
  </xsl:template>
</xsl:stylesheet>

有关工作示例,请参见http://xsltransform.net/asnmyT

我看到您忘记了上下文项已更改,例如在for-each循环中。

另请注意,我更改了displaySN模板。它包含MN参数,指的是“main”(PPP)元素。

displayCompositionEN模板也有一些变化。

我还添加了带有和属性的xsl:output元素 来生成 XHTML 输出,以便在 xsltransform测试站点中获取 HTML 视图。但是,如果您不需要它,只需将其删除。doctype-publicdoctype-system


推荐阅读