Messing XSL match patterns forming WordML document

2019-09-16 10:42发布

问题:

I have an xml structure. In xslt template for each position () in each list() I need to find position which attribute @out = 1, then I need to create a tree structure of categories it belongs to using positon's @pid attribute.

   <?xml version="1.0" encoding="ISO-8859-1"?>
    <Work>
    <Goods>
        <id="2196">
            <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." out = "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." out = "1" isKey="1" id="11600" pid="11599" description="Оборудование для тепловых испытаний образцов материалов с углерод-углеродным покрытием" />
    <pos  num="2.2.2." out = "1" isKey="1" id="11600" pid="11599" description="Оборудование для тепловых испытаний образцов материалов с углерод-углеродным покрытием" />
        </Goods>
        <Goods>
        <id="2111">
        </Goods>
         <Goods>
        <id="2112">
        </Goods>
    </Work>

For example if I want 4 positions with nums "9.2.1.2.10", "10.2.1","2.2.1","2.2.2" to be detailed for good with id=2196, I need some output like that:

+-------------------------------------------------------------------------------+
| Список оборудования, материалов и технологий, которые могут быть использованы |
| при создании ракетного оружия                                                 |
+-------------------------------------------------------------------------------+
| КАТЕГОРИЯ 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.     | Оборудование для тепловых испытаний образцов материалов...       |
+-------------------------------------------------------------------------------+

The following code for templates using for forming Word Document gives an error when trying to open a document:

  <xsl:template match="ns1:*"  mode="table1">
      <w:p wsp:rsidR="00785C21" wsp:rsidRPr="00A33D80" wsp:rsidRDefault="00785C21" wsp:rsidP="007E1332">
        <w:pPr>

        </w:pPr>
        <w:r>
          <w:rPr>
            <w:lang w:val="EN-US" />
          </w:rPr>
          <w:t>
            <xsl:text>Table output</xsl:text>
          </w:t>
        </w:r>

      </w:p>
    <xsl:variable name="shouldOutput">
      <xsl:apply-templates select="." mode="shouldOutput" />
    </xsl:variable>
    <xsl:if test="string-length($shouldOutput)">
      <w:tbl>
        <w:tblPr>
          <w:tblW w:w="0" w:type="auto" />
          <w:tblLook w:val="04A0" />
        </w:tblPr>
        <w:tblGrid>
          <w:gridCol w:w="222" />
          <w:gridCol w:w="222" />
        </w:tblGrid>

        <w:p wsp:rsidR="00785C21" wsp:rsidRPr="00A33D80" wsp:rsidRDefault="00785C21" wsp:rsidP="007E1332">
          <w:pPr>
          </w:pPr>
          <w:r>
            <w:rPr>
              <w:lang w:val="EN-US" />
            </w:rPr>
            <w:t>
              <xsl:text>Table output should output</xsl:text>
            </w:t>
          </w:r>

        </w:p>

        <xsl:apply-templates select="." />
      </w:tbl>
      <!--</table>-->
    </xsl:if>
  </xsl:template> <!--Matching analysis table-->


  <xsl:template match="ns1:*">
    <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><!-- 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="ns1:*" mode="row">
    <w:tr wsp:rsidR="007E1332" wsp:rsidRPr="005C4540" wsp:rsidTr="005C4540">
    <w:tc>

      <w:tcPr>
        <w:tcW w:w="0" w:type="auto" />
        <w:shd w:val="clear" w:color="auto" w:fill="auto" />
        <w:hmerge w:val="restart"/>
      </w:tcPr>

      <w:p wsp:rsidR="007E1332" wsp:rsidRPr="005C4540" wsp:rsidRDefault="007E1332" wsp:rsidP="005C4540">
        <w:pPr>
          <w:spacing w:before="20" w:after="20" />
          <w:rPr>
            <w:rFonts w:cs="Arial" />
          </w:rPr>
        </w:pPr>

        <w:r wsp:rsidRPr="005C4540">
          <w:rPr>
            <w:rFonts w:ascii="Calibri" w:h-ansi="Calibri" w:cs="Calibri" />
            <wx:font wx:val="Calibri" />
            <w:b w:val="off" />
            <w:color w:val="auto" />
            <w:lang w:val="EN-US" />
          </w:rPr>
          <w:t>
            <xsl:value-of select="@description" />
          </w:t>
        </w:r>
      </w:p>
    </w:tc>


    <w:tc>

      <w:tcPr>
        <w:tcW w:w="0" w:type="auto" />
        <w:shd w:val="clear" w:color="auto" w:fill="auto" />
        <w:hmerge w:val ="continue"/>
      </w:tcPr>

      <w:p wsp:rsidR="007E1332" wsp:rsidRPr="005C4540" wsp:rsidRDefault="007E1332" wsp:rsidP="005C4540">
        <w:pPr>
          <w:spacing w:before="20" w:after="20" />
          <w:rPr>
            <w:rFonts w:cs="Arial" />
          </w:rPr>
        </w:pPr>
      </w:p>
    </w:tc>

    </w:tr>

  </xsl:template>


  <xsl:template match="ns1:pos[@num]" mode="row">
    <w:tr wsp:rsidR="007E1332" wsp:rsidRPr="005C4540" wsp:rsidTr="005C4540">

      <w:tc>

        <w:tcPr>
          <w:tcW w:w="0" w:type="auto" />
          <w:shd w:val="clear" w:color="auto" w:fill="auto" />
        </w:tcPr>

        <w:p wsp:rsidR="007E1332" wsp:rsidRPr="005C4540" wsp:rsidRDefault="007E1332" wsp:rsidP="005C4540">
          <w:pPr>
            <w:spacing w:before="20" w:after="20" />
            <w:rPr>
              <w:rFonts w:cs="Arial" />
            </w:rPr>
          </w:pPr>
          <w:r wsp:rsidRPr="005C4540">
            <w:rPr>
              <w:rFonts w:ascii="Calibri" w:h-ansi="Calibri" w:cs="Calibri" />
              <wx:font wx:val="Calibri" />
              <w:b w:val="off" />
              <w:color w:val="auto" />
              <w:lang w:val="EN-US" />
            </w:rPr>
            <w:t>
              <xsl:value-of select="@num" />
            </w:t>
          </w:r>
        </w:p>

      </w:tc>


      <w:tc>

        <w:tcPr>
          <w:tcW w:w="0" w:type="auto" />
          <w:shd w:val="clear" w:color="auto" w:fill="auto" />
        </w:tcPr>

        <w:p wsp:rsidR="007E1332" wsp:rsidRPr="005C4540" wsp:rsidRDefault="007E1332" wsp:rsidP="005C4540">
          <w:pPr>
            <w:spacing w:before="20" w:after="20" />
            <w:rPr>
              <w:rFonts w:cs="Arial" />
            </w:rPr>
          </w:pPr>
          <w:r wsp:rsidRPr="005C4540">
            <w:rPr>
              <w:rFonts w:ascii="Calibri" w:h-ansi="Calibri" w:cs="Calibri" />
              <wx:font wx:val="Calibri" />
              <w:b w:val="off" />
              <w:color w:val="auto" />
              <w:lang w:val="EN-US" />
            </w:rPr>
            <w:t>
              <xsl:value-of select="@description" />
            </w:t>
          </w:r>
        </w:p>
      </w:tc>

    </w:tr>

  </xsl:template> <!-- special case for pos elements with a @num - produce two columns -->



  <xsl:template match="ns1:*[@out='1']" mode="shouldOutput">1</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="ns1:*" mode="shouldOutput">
    <xsl:apply-templates select="key('elementsByPid', @id)" mode="shouldOutput"/>
  </xsl:template>

At the top of the xsl stylesheet I have a key declaration:

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

In main template for Goods:

<xsl:template match="/ns1:Work/ns1:Goods">
    <ns1:Goods>
      <xsl:for-each select="@ns1:*|@*[namespace-uri()='']">
        <xsl:attribute name="{name()}" namespace="{namespace-uri()}">
          <xsl:value-of select="." />
        </xsl:attribute>
      </xsl:for-each>

<!--Here is some WordML code-->

<!--Here I call to one of the above templates to form lists for the current good-->
<xsl:apply-templates select="ns1:list" mode="table" />

    </ns1:Goods>
  </xsl:template><!--/Goods товары в блоке описания-->

I can't find where is the mistake, but I think I've messed something with match patterns, because for simple html file everything worked fine

标签: xml xslt wordml