使用 XSLT 转换组合项目

Combining items using XSLT Transform

我有以下 XML 结构:

<row>
  <item>Controller</item>
</row>
<row>
  <item>****************</item>
</row>
<row>
  <item>Serial Number</item>
  <item>Name</item>
  <item>Controller index</item>
  <item>Firmware Version</item>
  <item> Product Rev.</item>
  <item>Mode</item>
  <item>Type</item>
  <item>ExtName</item>
  <item>Comment</item>
</row>
<row>
  <item>#0A384D3</item>
  <item>=&#34;AdventistBolingbrook&#34;</item>
  <item>0</item>
  <item>=&#34;7.0/2.1&#34;</item>
  <item>A00</item>
  <item>MA 1000 &amp; 2000</item>
  <item>Master</item>
  <item></item>
  <item></item>
</row>
<row>
  <item>Base Unit</item>
</row>
<row>
  <item>****************</item>
</row>
<row>
  <item>Serial Number</item>
  <item>Name</item>
  <item>Controller Index</item>
  <item>Port Index</item>
  <item>Slot Index</item>
  <item>Firmware Version</item>
  <item>Product Rev.</item>
  <item>DL Input Power Status</item>
  <item>DL Power Interface Type</item>
  <item>DL AGC Status</item>
  <item>DL AGC Atten. Value</item>
  <item>DL DCA Manual Override</item>
  <item>DL Power</item>
  <item>UL Atten. Value</item>
  <item>ExtName</item>
  <item>Comment</item>
</row>
<row>
  <item>#0A3651B</item>
  <item>VZW BU              </item>
  <item>0</item>
  <item>1</item>
  <item>1</item>
  <item>=&#34;4.1&#34;</item>
  <item>N/A </item>
  <item>Normal</item>
  <item>RIU</item>
  <item>OFF</item>
  <item>6</item>
  <item>6</item>
  <item>-21</item>
  <item>0</item>
  <item></item>
  <item></item>
</row>
<row>
  <item>#0A3651B</item>
  <item>VZW BU              </item>
  <item>0</item>
  <item>1</item>
  <item>2</item>
  <item>=&#34;4.1&#34;</item>
  <item>N/A </item>
  <item>Normal</item>
  <item>RIU</item>
  <item>OFF</item>
  <item>7</item>
  <item>7</item>
  <item>-27</item>
  <item>0</item>
  <item></item>
  <item></item>
</row>
<row>
  <item>#50772EC</item>
  <item>                    </item>
  <item>0</item>
  <item>4</item>
  <item>1</item>
  <item>=&#34;5.3&#34;</item>
  <item>N/A </item>
  <item>Normal</item>
  <item>RIU</item>
  <item>OFF</item>
  <item>2</item>
  <item>2</item>
  <item>-22</item>
  <item>0</item>
  <item></item>
  <item></item>
</row>
<row>
  <item>#50772EC</item>
  <item>                    </item>
  <item>0</item>
  <item>4</item>
  <item>2</item>
  <item>=&#34;5.3&#34;</item>
  <item>N/A </item>
  <item>Normal</item>
  <item>RIU</item>
  <item>OFF</item>
  <item>3</item>
  <item>3</item>
  <item>-18</item>
  <item>0</item>
  <item></item>
  <item></item>
</row>

我需要将其转换为:

<row>
  <item>Controller</item>
  <item>#0A384D3</item>
  <item>=&#34;AdventistBolingbrook&#34;</item>
  <item>0</item>
  <item>=&#34;7.0/2.1&#34;</item>
  <item>A00</item>
  <item>MA 1000 &amp; 2000</item>
  <item>Master</item>
  <item></item>
  <item></item>
</row>
<row>
  <item>Base Unit</item>
  <item>#0A3651B</item>
  <item>VZW BU              </item>
  <item>0</item>
  <item>1</item>
  <item>1</item>
  <item>=&#34;4.1&#34;</item>
  <item>N/A </item>
  <item>Normal</item>
  <item>RIU</item>
  <item>OFF</item>
  <item>6</item>
  <item>6</item>
  <item>-21</item>
  <item>0</item>
  <item></item>
  <item></item>
</row>
<row>
  <item>Base Unit</item>
  <item>#0A3651B</item>
  <item>VZW BU              </item>
  <item>0</item>
  <item>1</item>
  <item>2</item>
  <item>=&#34;4.1&#34;</item>
  <item>N/A </item>
  <item>Normal</item>
  <item>RIU</item>
  <item>OFF</item>
  <item>7</item>
  <item>7</item>
  <item>-27</item>
  <item>0</item>
  <item></item>
  <item></item>
</row>
<row>
  <item>Base Unit</item>
  <item>#50772EC</item>
  <item>                    </item>
  <item>0</item>
  <item>4</item>
  <item>1</item>
  <item>=&#34;5.3&#34;</item>
  <item>N/A </item>
  <item>Normal</item>
  <item>RIU</item>
  <item>OFF</item>
  <item>2</item>
  <item>2</item>
  <item>-22</item>
  <item>0</item>
  <item></item>
  <item></item>
</row>
<row>
  <item>Base Unit</item>
  <item>#50772EC</item>
  <item>                    </item>
  <item>0</item>
  <item>4</item>
  <item>2</item>
  <item>=&#34;5.3&#34;</item>
  <item>N/A </item>
  <item>Normal</item>
  <item>RIU</item>
  <item>OFF</item>
  <item>3</item>
  <item>3</item>
  <item>-18</item>
  <item>0</item>
  <item></item>
  <item></item>
</row>

那么这里的规则是什么...

  1. 我只需要保留第一项以 # 开头的行。作为 xpath,这表示为 //row/item[1][matches(.,"(#)")]/..
  2. 每当我有一行,其中第一项以 # 开头时,我需要从第一个前同级之前的行中复制第一项,其中第一个项目以 *** 开头。

这是一个更图形化的版本。

<row>
  <item>Controller</item>    <- I need to include this value into each of these
</row>                                                             |
<row>                                                              |
  <item>****************</item>                                    |
</row>                                                             |
<row>                                                              |
  <item>Serial Number</item>                                       |
  <item>Name</item>                                                |
  <item>Controller index</item>                                    |
  <item>Firmware Version</item>                                    |
  <item> Product Rev.</item>                                       |
  <item>Mode</item>                                                |
  <item>Type</item>                                                |
  <item>ExtName</item>                                             |
  <item>Comment</item>                                             |
</row>                                                            \ /
<row>             <- I want to include this row as its first item starts with `#`
  <item>#0A384D3</item>                                            |
  <item>=&#34;AdventistBolingbrook&#34;</item>                     |
  <item>0</item>                                                   |
  <item>=&#34;7.0/2.1&#34;</item>                                  |
  <item>A00</item>                                                 |
  <item>MA 1000 &amp; 2000</item>                                  |
  <item>Master</item>                                              |
  <item></item>                                                    |
  <item></item>                                                    |
</row>                                                            \ /
<row>             <- I want to include this row as its first item starts with `#`
  <item>#0A384D3</item>
  <item>=&#34;AdventistBolingbrook&#34;</item>
  <item>0</item>
  <item>=&#34;7.0/2.1&#34;</item>
  <item>A00</item>
  <item>MA 1000 &amp; 2000</item>
  <item>Master</item>
  <item></item>
  <item></item>
</row>

给定一个格式正确的输入,例如:

XML

<rows>
    <row>
        <item>Controller</item>
    </row>
    <row>
        <item>****************</item>
    </row>
    <row>
        <item>Serial Number</item>
        <item>Name</item>
        <item>Controller index</item>
        <item>Firmware Version</item>
        <item> Product Rev.</item>
        <item>Mode</item>
        <item>Type</item>
        <item>ExtName</item>
        <item>Comment</item>
    </row>
    <row>
        <item>#0A384D3</item>
        <item>=&#34;AdventistBolingbrook&#34;</item>
        <item>0</item>
        <item>=&#34;7.0/2.1&#34;</item>
        <item>A00</item>
        <item>MA 1000 &amp; 2000</item>
        <item>Master</item>
        <item></item>
        <item></item>
    </row>
    <row>
        <item>Base Unit</item>
    </row>
    <row>
        <item>****************</item>
    </row>
    <row>
        <item>Serial Number</item>
        <item>Name</item>
        <item>Controller Index</item>
        <item>Port Index</item>
        <item>Slot Index</item>
        <item>Firmware Version</item>
        <item>Product Rev.</item>
        <item>DL Input Power Status</item>
        <item>DL Power Interface Type</item>
        <item>DL AGC Status</item>
        <item>DL AGC Atten. Value</item>
        <item>DL DCA Manual Override</item>
        <item>DL Power</item>
        <item>UL Atten. Value</item>
        <item>ExtName</item>
        <item>Comment</item>
    </row>
    <row>
        <item>#0A3651B</item>
        <item>VZW BU              </item>
        <item>0</item>
        <item>1</item>
        <item>1</item>
        <item>=&#34;4.1&#34;</item>
        <item>N/A </item>
        <item>Normal</item>
        <item>RIU</item>
        <item>OFF</item>
        <item>6</item>
        <item>6</item>
        <item>-21</item>
        <item>0</item>
        <item></item>
        <item></item>
    </row>
    <row>
        <item>#0A3651B</item>
        <item>VZW BU              </item>
        <item>0</item>
        <item>1</item>
        <item>2</item>
        <item>=&#34;4.1&#34;</item>
        <item>N/A </item>
        <item>Normal</item>
        <item>RIU</item>
        <item>OFF</item>
        <item>7</item>
        <item>7</item>
        <item>-27</item>
        <item>0</item>
        <item></item>
        <item></item>
    </row>
    <row>
        <item>#50772EC</item>
        <item>                    </item>
        <item>0</item>
        <item>4</item>
        <item>1</item>
        <item>=&#34;5.3&#34;</item>
        <item>N/A </item>
        <item>Normal</item>
        <item>RIU</item>
        <item>OFF</item>
        <item>2</item>
        <item>2</item>
        <item>-22</item>
        <item>0</item>
        <item></item>
        <item></item>
    </row>
    <row>
        <item>#50772EC</item>
        <item>                    </item>
        <item>0</item>
        <item>4</item>
        <item>2</item>
        <item>=&#34;5.3&#34;</item>
        <item>N/A </item>
        <item>Normal</item>
        <item>RIU</item>
        <item>OFF</item>
        <item>3</item>
        <item>3</item>
        <item>-18</item>
        <item>0</item>
        <item></item>
        <item></item>
    </row>
</rows>

以下样式表:

XSLT 2.0

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

<xsl:template match="/rows">
    <xsl:copy>
        <xsl:for-each-group select="row" group-starting-with="row[item='****************']">
            <xsl:variable name="title-item" select="preceding-sibling::row[1]/item" />
            <xsl:for-each select="current-group()[starts-with(item[1], '#')]">
                <row>
                    <xsl:copy-of select="$title-item, *"/>
                </row>
            </xsl:for-each>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

将 return:

结果

<?xml version="1.0" encoding="UTF-8"?>
<rows>
   <row>
      <item>Controller</item>
      <item>#0A384D3</item>
      <item>="AdventistBolingbrook"</item>
      <item>0</item>
      <item>="7.0/2.1"</item>
      <item>A00</item>
      <item>MA 1000 &amp; 2000</item>
      <item>Master</item>
      <item/>
      <item/>
   </row>
   <row>
      <item>Base Unit</item>
      <item>#0A3651B</item>
      <item>VZW BU              </item>
      <item>0</item>
      <item>1</item>
      <item>1</item>
      <item>="4.1"</item>
      <item>N/A </item>
      <item>Normal</item>
      <item>RIU</item>
      <item>OFF</item>
      <item>6</item>
      <item>6</item>
      <item>-21</item>
      <item>0</item>
      <item/>
      <item/>
   </row>
   <row>
      <item>Base Unit</item>
      <item>#0A3651B</item>
      <item>222VZW BU              </item>
      <item>0</item>
      <item>1</item>
      <item>2</item>
      <item>="4.1"</item>
      <item>N/A </item>
      <item>Normal</item>
      <item>RIU</item>
      <item>OFF</item>
      <item>7</item>
      <item>7</item>
      <item>-27</item>
      <item>0</item>
      <item/>
      <item/>
   </row>
   <row>
      <item>Base Unit</item>
      <item>#50772EC</item>
      <item>                    </item>
      <item>3330</item>
      <item>4</item>
      <item>1</item>
      <item>="5.3"</item>
      <item>N/A </item>
      <item>Normal</item>
      <item>RIU</item>
      <item>OFF</item>
      <item>2</item>
      <item>2</item>
      <item>-22</item>
      <item>0</item>
      <item/>
      <item/>
   </row>
   <row>
      <item>Base Unit</item>
      <item>#50772EC</item>
      <item>                    </item>
      <item>0</item>
      <item>4</item>
      <item>2</item>
      <item>="5.3"</item>
      <item>N/A </item>
      <item>Normal</item>
      <item>RIU</item>
      <item>OFF</item>
      <item>3</item>
      <item>3</item>
      <item>-18</item>
      <item>0</item>
      <item/>
      <item/>
   </row>
</rows>

哪个 AFAICT 与您的预期输出相同,除了具有根元素、空元素的自闭合和某些字符的编码。