0

我有一个xml结构。在每个 list() 中每个位置 () 的 xslt 模板中,我需要找到属性 @out = 1 的位置,然后我需要使用 positon 的 @pid 属性创建它所属的类别的树结构。

<?xml version="1.0" encoding="ISO-8859-1"?>
    <Good id = "2196">
    <lists>
        <list  num="1050" id = "2531" description="Список оборудования и материалов двойного назначения и соответствующих технологий, применяемых в ядерных целях">
          <part  num="1">
            <pos  isKey="0" id="2532" pid="2531" description="Раздел 1. Промышленное оборудование" />
            <pos  num="1.2." isKey="0" id="2554" pid="2532" description="Испытательное и производственное оборудование" />
            <pos  num="1.2.6." isKey="0" id="2591" pid="2554" description="Системы для вибрационных испытаний, оборудование и компоненты, такие, как:" />
            <pos  num="1.2.6.1." isKey="1" id="2592" pid="2591" description="Электродинамические системы для вибрационных испытаний" />
            <pos  num="1.2.6.4." isKey="1" id="2595" pid="2591" description="Конструкции для крепления испытуемой детали и электронные блоки" />
          </part>
        </list>
        <list  num="1090" id = "3029" description="Список оборудования, материалов и технологий, которые могут быть использованы при создании ракетного оружия">
          <part  num="2">
            <pos  isKey="0" id="3033" pid="3029" description="КАТЕГОРИЯ II" />
            <pos  isKey="0" id="3040" pid="3033" description="Раздел 9. Измерительное, навигационное и пеленгаторное оборудование и системы" />
            <pos  isKey="0" id="3041" pid="3033" description="Раздел 10. Системы управления полетом" />
            <pos  isKey="0" id="3043" pid="3033" description="Раздел 12. Оборудование для обеспечения пуска" />
            <pos  isKey="0" id="3046" pid="3033" description="Раздел 15. Испытательные системы и оборудование" />
            <pos  num="9.2." isKey="0" id="3333" pid="3040" description="Испытательное и производственное оборудование" />
            <pos  num="9.2.1." isKey="0" id="3334" pid="3333" description="Производственное, испытательное.." />
            <pos  num="9.2.1.2" isKey="0" id="3339" pid="3334" description="Испытательное оборудование для инерциальной аппаратуры:" />
            <pos  num="9.2.1.2.3." isKey="1" id="3342" pid="3339" description="Испытательный стенд стабилизирующего элемента ИИБ;" />
            <pos  num="9.2.1.2.5." isKey="1" id="3344" pid="3339" description="Установка для проверки и настройки гироскопа;" />
            <pos  num="9.2.1.2.9." isKey="1" id="3348" pid="3339" description="Центрифуга для проверки подшипников (опор) гироскопа;" />
            <pos  num="9.2.1.2.10." isKey="1" out="1" id="3349" pid="3339" description="Установка для осевой регулировки акселерометра;" />
            <pos  num="9.2.1.2.11." isKey="1" id="3350" pid="3339" description="Установка для проверки акселерометра" />
            <pos  num="9.2.2." isKey="0" id="3351" pid="3333" description="Испытательное, калибровочное и регулировочное оборудование:" />
            <pos  num="9.2.2.3." isKey="1" id="3354" pid="3351" description="Динамические моделирующие стенды/столы вращения)" />
            <pos  num="9.2.2.4." isKey="1" id="3355" pid="3351" description="Поворотные столы" />
            <pos  num="9.2.2.5." isKey="1" id="3356" pid="3351" description="Центрифуги, способные создавать ускорения более 100 g" />
            <pos  num="10.2." isKey="0" id="3373" pid="3041" description="Испытательное и производственное оборудование" />
            <pos  num="10.2.1." isKey="1" id="3374" pid="3373" description="Испытательное, калибровочное и регулировочное оборудование" />
            <pos  num="12.1." isKey="0" id="3399" pid="3043" description="Оборудование, сборочные единицы и комплектующие" />
            <pos  num="12.1.1." isKey="1" id="3400" pid="3399" description="Устройства и приборы, разработанные или модифицированные для обслуживания, проверки" />
        </part>
        </list>
        <list  num="1030" id="6648" description="Список товаров и технологий двойного назначения, которые могут быть использованы при создании вооружений и военной техники">
          <part  num="4">
            <pos  isKey="0" id="6679" pid="6648" description="Раздел 4. Товары и технологии, вывоз которых с территории РФ" />
            <pos  isKey="0" id="6681" pid="6679" description="Категория 2. Перспективные материалы" />
            <pos  num="2.2." isKey="0" id="11599" pid="6681" description="Испытательное, контрольное и производственное оборудование" />
            <pos  num="2.2.1." isKey="1" id="11600" pid="11599" description="Оборудование для тепловых испытаний образцов материалов с углерод-углеродным покрытием" />

例如编号为“9.2.1.2.10”的位置。我需要一些像word文档这样的输出:

 +-------------------------------------------------------------------------------+
 | Список оборудования, материалов и технологий, которые могут быть использованы |
 | при создании ракетного оружия                                                 |
 +-------------------------------------------------------------------------------+
 | КАТЕГОРИЯ II                                                                  |
 +-------------------------------------------------------------------------------+
 | Раздел 9. Измерительное, навигационное и пеленгаторное оборудование и системы |
 +-------------------------------------------------------------------------------+
 | 9.2.       | Испытательное и производственное оборудование                    |
 | 9.2.1.     | Производственное, испытательное..                                |
 | 9.2.1.2.   | Испытательное оборудование для инерциальной аппаратуры           |
 | 9.2.1.2.10.| Установка для осевой регулировки акселерометра                   |
 +-------------------------------------------------------------------------------+

但是,如果我想要 4 个位置的 nums 为“9.2.1.2.10”、“10.2.1”、“2.2.1”、“2.2.2”,我需要一些这样的输出:

 +-------------------------------------------------------------------------------+
 | Список оборудования, материалов и технологий, которые могут быть использованы |
 | при создании ракетного оружия                                                 |
 +-------------------------------------------------------------------------------+
 | КАТЕГОРИЯ II                                                                  |
 +-------------------------------------------------------------------------------+
 | Раздел 9. Измерительное, навигационное и пеленгаторное оборудование и системы |
 +-------------------------------------------------------------------------------+
 | 9.2.       | Испытательное и производственное оборудование                    |
 | 9.2.1.     | Производственное, испытательное..                                |
 | 9.2.1.2.   | Испытательное оборудование для инерциальной аппаратуры           |
 | 9.2.1.2.10.| Установка для осевой регулировки акселерометра                   |
 +-------------------------------------------------------------------------------+
 | Раздел 10. Системы управления полетом                                         |
 +-------------------------------------------------------------------------------+
 | 10.2.      | Испытательное и производственное оборудование                    |
 | 10.2.1     | Испытательное, калибровочное и регулировочное оборудование       |
 +-------------------------------------------------------------------------------+


 +-------------------------------------------------------------------------------+
 | Список товаров и технологий двойного назначения, которые могут быть           |
 |использованы при создании вооружений и военной техники                         |
 +-------------------------------------------------------------------------------+
 | Раздел 4. Товары и технологии, вывоз которых с территории РФ                  |
 +-------------------------------------------------------------------------------+
 | Категория 2. Перспективные материалы                                          |
 +-------------------------------------------------------------------------------+
 | 2.2.       | Испытательное, контрольное и производственное оборудование       |
 | 2.2.1.     | Оборудование для тепловых испытаний образцов материалов...       |
 | 2.2.2.     | Оборудование для тепловых испытаний образцов материалов...       |
 +-------------------------------------------------------------------------------+

到目前为止,我尝试过这样的事情:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">


<xsl:template match="/">

  <html>
  <body>
  <h2>Lists</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th>Id</th>
        <th>parentID</th>
      </tr>
<xsl:apply-templates select="/goods/good/list/part/pos[@out=1]"/>
    </table>
  </body>
  </html>
</xsl:template>

<xsl:template match="/goods/good/list/part/pos[@out=1]">
<xsl:variable name="pid" select="./@pid" />
  Key node: <span style="color:#ff0000">
  <xsl:value-of select="./@num"/><xsl:text>, id =  </xsl:text>
<xsl:value-of select="./@id"/><xsl:text>, pid =  </xsl:text>
<xsl:value-of select="./@pid"/>
</span><br/>
<xsl:call-template name = "while">
 <xsl:with-param name="param" select="$pid"/>
</xsl:call-template>


  <br />
</xsl:template>



<xsl:template name = "while">
<xsl:param name="param"/>
<xsl:variable name="pid" select="../pos[@id = $param]/@pid"/>

<tr>
<td><xsl:value-of select="../pos[@id = $param]/@id"/></td>
<td><xsl:value-of select="../pos[@id = $param]/@pid"/></td>
</tr>

Param: <span style="color:#ff0000">
<xsl:value-of select="$param"/>
</span>

Inner var: <span style="color:#ff0000">
<xsl:value-of select="$pid"/>
</span>


<xsl:if test="$pid">
<br/>
<xsl:call-template name = "while">
 <xsl:with-param name="param" select="$pid"/>
</xsl:call-template>
</xsl:if>
</xsl:template>

</xsl:stylesheet>

可能有更好的方法来完成这项任务吗?

4

1 回答 1

2

遵循pidtoid链接链的规则似乎是,对于pos具有属性的元素,您需要两个单独的列,而对于其他情况(没有的元素或未调用的元素),需要num一个两列跨度。您可以使用key跟随链:tdposnumpos

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes" />

  <!-- key to look up any element with an id attribute based on the value of
       that id -->
  <xsl:key name="elementById" match="*[@id]" use="@id" />

  <xsl:template match="/">
    <html>
      <body>
      <h2>Lists</h2>
        <xsl:apply-templates select="//*[@out = '1']" mode="table" />
      </body>
    </html>
  </xsl:template>

  <xsl:template match="*" mode="table">
    <table>
      <xsl:apply-templates select="." />
    </table>
  </xsl:template>

  <!-- the main recursive logic - first produce the output for the next
       item in the pid->id chain, then produce a row for this element -->
  <xsl:template match="*">
    <xsl:apply-templates select="key('elementById', @pid)" />
    <tr>
      <td colspan="2"><xsl:value-of select="@description" /></td>
    </tr>
  </xsl:template>

  <!-- special case for pos elements with a @num - produce two columns -->
  <xsl:template match="pos[@num]">
    <xsl:apply-templates select="key('elementById', @pid)" />
    <tr>
      <td><xsl:value-of select="@num" /></td>
      <td><xsl:value-of select="@description" /></td>
    </tr>
  </xsl:template>

</xsl:stylesheet>

当我们到达没有pid属性的元素时,递归将自动停止,因为在这种情况下键将不匹配任何内容。


如果您想对树中的父链接进行去重和分组,那么您必须自上而下而不是自下而上,按照反向链接进行操作:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes" />

  <!-- key to look up any element with an id attribute based on the value of
       that id -->
  <xsl:key name="elementsByPid" match="*[@pid]" use="@pid" />

  <xsl:template match="/">
    <html>
      <body>
      <h2>Lists</h2>
        <xsl:apply-templates select="/Good/lists/list" mode="table" />
      </body>
    </html>
  </xsl:template>

  <xsl:template match="*" mode="table">
    <xsl:variable name="shouldOutput">
      <xsl:apply-templates select="." mode="shouldOutput" />
    </xsl:variable>
    <xsl:if test="string-length($shouldOutput)">
      <table>
        <xsl:apply-templates select="." />
      </table>
    </xsl:if>
  </xsl:template>

  <!-- the main recursive logic - first produce output for this row, then
       process any of the children (in the id->pid chain) that need to be
       output -->
  <xsl:template match="*">
    <xsl:apply-templates select="." mode="row" />
    <xsl:for-each select="key('elementsByPid', @id)">
      <xsl:variable name="shouldOutput">
        <xsl:apply-templates select="." mode="shouldOutput" />
      </xsl:variable>
      <xsl:if test="string-length($shouldOutput)">
        <xsl:apply-templates select="." />
      </xsl:if>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="*" mode="row">
    <tr>
      <td colspan="2"><xsl:value-of select="@description" /></td>
    </tr>
  </xsl:template>

  <!-- special case for pos elements with a @num - produce two columns -->
  <xsl:template match="pos[@num]" mode="row">
    <tr>
      <td><xsl:value-of select="@num" /></td>
      <td><xsl:value-of select="@description" /></td>
    </tr>
  </xsl:template>


  <!-- check whether this node should be output by checking whether it, or any
       of its descendants in the id->pid tree, has @out=1.  The template will
       return an empty RTF for nodes that should not be output, and an RTF
       containing a text node with one or more "1" characters for nodes that
       should.  -->
  <xsl:template match="*[@out='1']" mode="shouldOutput">1</xsl:template>
  <xsl:template match="*" mode="shouldOutput">
    <xsl:apply-templates select="key('elementsByPid', @id)"
         mode="shouldOutput"/>
  </xsl:template>

</xsl:stylesheet>

对于大型输入文档,这将是相当低效的,因为它必须在每一层都遵循整个 id->pid 链接链一直到底部,以检查当前节点是否在链中具有任何 out="1"后代。如果您可以对文档进行预处理以提前计算出这些链并标记链中的每个链接,out="1"那么逻辑将更加简单和高效。

于 2013-10-14T11:40:36.817 回答