【问题标题】:Select nodes based on attribute value of a node根据节点的属性值选择节点
【发布时间】:2019-09-02 08:37:14
【问题描述】:

我需要将 xml 文件报告到 html 中的表中。我正确选择了我需要的节点,但只有当一个节点包含某个值时,我才想在表中包含一组节点。 必须创建该表来报告每个带有传感器的站,并且只有处于活动状态的扇区(要处于活动状态,属性名称=活动需要具有值=1)。所以如果它是活跃的,我需要报告节点中所有活跃的属性,包括属性左、右和名称,而不仅仅是活跃的。如果它不是 Active (value = 0),它只需要报告 Sector 的 id。

另一个问题是在另一列(右侧)中有一个 Station id=1 的表格,而不是 Station id=0 的底部。

为了更好地解释,我在下面展示了我到目前为止所做的一些代码。

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

<map>
    <class type="Station" id="0">
        <attribute name="Name" value="Tom"/>
        <attribute name="Width" value="15000"/>
        <attribute name="Height" value="10000"/>
        <class type="Sensor" id="1">
            <attribute name="Name" value="Pressure"/>
            <attribute name="Position" value="222"/>
        </class>
        <class type="Sector" id="0">
            <attribute name="Left" value="100"/>
            <attribute name="Right" value="1000"/>
            <attribute name="Active" value="1"/>
            <attribute name="Name" value="Begin"/>
        </class>
        <class type="Sector" id="1">
            <attribute name="Left" value="5000"/>
            <attribute name="Right" value="5500"/>
            <attribute name="Active" value="0"/>
            <attribute name="Name" value="End"/>
        </class>
    </class>
    <class type="Station" id="1">
        <attribute name="Name" value="Mark"/>
        <attribute name="Width" value="12500"/>
        <attribute name="Height" value="20000"/>
        <class type="Sensor" id="1">
            <attribute name="Name" value="Pressure"/>
            <attribute name="Position" value="420"/>
        </class>
        <class type="Sector" id="0">
            <attribute name="Left" value="200"/>
            <attribute name="Right" value="2000"/>
            <attribute name="Active" value="0"/>
            <attribute name="Name" value="Begin"/>
        </class>
        <class type="Sector" id="1">
            <attribute name="Left" value="15000"/>
            <attribute name="Right" value="15500"/>
            <attribute name="Active" value="1"/>
            <attribute name="Name" value="End"/>
        </class>
    </class>
</map>

使用 xsl:

<?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>
      <style>
        table, th, td {
        border: 1px solid black;
        border-spacing: 0px;
        }
      </style>
      <body>
        <h2>Item</h2>
        <table>
          <!--xsl:apply-templates/> -->
          <tr bgcolor = "#9acd32">
            <th>Type</th>
            <th>ID</th>
            <th>Name</th>
            <th>Value</th>
          </tr>
          <xsl:apply-templates select="map"/>
        </table>
      </body> 
    </html> 
  </xsl:template>  

  <xsl:template match="map">
    <xsl:apply-templates select="class"/>
  </xsl:template>

  <xsl:template match="class">
    <tr bgcolor = "#ff0000">
      <td> <xsl:value-of select="@type"/> </td> 
      <td> <xsl:value-of select="@id+1"/> </td> 
      <td></td> 
      <td></td> 
    </tr> 
    <xsl:apply-templates select="attribute"/>
    <xsl:call-template name="Sensortype"/>
    <xsl:call-template name="Sectortype"/>
  </xsl:template>

  <xsl:template match="attribute">
    <tr>
      <td></td> 
      <td></td> 
      <td> <xsl:value-of select="@name"/></td>
      <td> <xsl:value-of select="@value"/></td>
    </tr>

  </xsl:template>

  <xsl:template name="Sensortype">
    <xsl:for-each select="class"> 
     <xsl:if test="@type = 'Sensor'">
      <tr bgcolor = "#ffff00">
        <td> Sensor: <xsl:value-of select="@type"/> </td>
        <td> <xsl:value-of select="@id+1"/> </td>
        <td></td> 
        <td></td> 
      </tr> 
      <xsl:call-template name="sensorname"/>
    </xsl:if>
  </xsl:for-each>
</xsl:template>

<xsl:template name="sensorname">
  <xsl:for-each select="attribute"> 
    <tr>
      <td></td> 
      <td></td> 
      <td> Sensor: <xsl:value-of select="@name"/></td>
      <td> <xsl:value-of select="@value"/></td>
    </tr>
  </xsl:for-each>
</xsl:template>

<xsl:template name="Sectortype">
  <xsl:for-each select="class"> 
   <xsl:if test="@type = 'Sector'">
    <tr bgcolor = "#00ffff">
      <td> Sector: <xsl:value-of select="@type"/> </td>
      <td> <xsl:value-of select="@id+1"/> </td>
      <td></td> 
      <td></td> 
    </tr>
    <xsl:call-template name="Sectorname"/>
  </xsl:if>
</xsl:for-each>
</xsl:template>

<xsl:template name="Sectorname">
  <xsl:for-each select="attribute">
    <xsl:if test="@name = 'Active' and @value = 1">
      <xsl:for-each select=".">
        <tr>
          <td></td> 
          <td></td> 
          <td> Sector: <xsl:value-of select="@name"/></td>
          <td> <xsl:value-of select="@value"/></td>
        </tr>
      </xsl:for-each>
    </xsl:if>    
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

这是实际结果:

<html>
   <style>
        table, th, td {
        border: 1px solid black;
        border-spacing: 0px;
        }
      </style>
   <body>
      <h2>Item</h2>
      <table>
         <tr bgcolor="#9acd32">
            <th>Type</th>
            <th>ID</th>
            <th>Name</th>
            <th>Value</th>
         </tr>
         <tr bgcolor="#ff0000">
            <td>Station</td>
            <td>1</td>
            <td/>
            <td/>
         </tr>
         <tr>
            <td/>
            <td/>
            <td>Name</td>
            <td>Tom</td>
         </tr>
         <tr>
            <td/>
            <td/>
            <td>Width</td>
            <td>15000</td>
         </tr>
         <tr>
            <td/>
            <td/>
            <td>Height</td>
            <td>10000</td>
         </tr>
         <tr bgcolor="#ffff00">
            <td> Sensor: Sensor</td>
            <td>2</td>
            <td/>
            <td/>
         </tr>
         <tr>
            <td/>
            <td/>
            <td> Sensor: Name</td>
            <td>Pressure</td>
         </tr>
         <tr>
            <td/>
            <td/>
            <td> Sensor: Position</td>
            <td>222</td>
         </tr>
         <tr bgcolor="#00ffff">
            <td> Sector: Sector</td>
            <td>1</td>
            <td/>
            <td/>
         </tr>
         <tr>
            <td/>
            <td/>
            <td> Sector: Active</td>
            <td>1</td>
         </tr>
         <tr bgcolor="#00ffff">
            <td> Sector: Sector</td>
            <td>2</td>
            <td/>
            <td/>
         </tr>
         <tr bgcolor="#ff0000">
            <td>Station</td>
            <td>2</td>
            <td/>
            <td/>
         </tr>
         <tr>
            <td/>
            <td/>
            <td>Name</td>
            <td>Mark</td>
         </tr>
         <tr>
            <td/>
            <td/>
            <td>Width</td>
            <td>12500</td>
         </tr>
         <tr>
            <td/>
            <td/>
            <td>Height</td>
            <td>20000</td>
         </tr>
         <tr bgcolor="#ffff00">
            <td> Sensor: Sensor</td>
            <td>2</td>
            <td/>
            <td/>
         </tr>
         <tr>
            <td/>
            <td/>
            <td> Sensor: Name</td>
            <td>Pressure</td>
         </tr>
         <tr>
            <td/>
            <td/>
            <td> Sensor: Position</td>
            <td>420</td>
         </tr>
         <tr bgcolor="#00ffff">
            <td> Sector: Sector</td>
            <td>1</td>
            <td/>
            <td/>
         </tr>
         <tr bgcolor="#00ffff">
            <td> Sector: Sector</td>
            <td>2</td>
            <td/>
            <td/>
         </tr>
         <tr>
            <td/>
            <td/>
            <td> Sector: Active</td>
            <td>1</td>
         </tr>
      </table>
   </body>
</html>

这里使用 xsl:if 我只能获得具有活动值的行,而不能获得同一节点的其他属性。这是预期的输出:

<html>
   <style>
        table, th, td {
        border: 1px solid black;
        border-spacing: 0px;
        }
      </style>
   <body>
      <h2>Item</h2>
      <table>
         <tr bgcolor="#9acd32">
            <th>Type</th>
            <th>ID</th>
            <th>Name</th>
            <th>Value</th>
         </tr>
         <tr bgcolor="#ff0000">
            <td>Station</td>
            <td>1</td>
            <td/>
            <td/>
         </tr>
         <tr>
            <td/>
            <td/>
            <td>Name</td>
            <td>Tom</td>
         </tr>
         <tr>
            <td/>
            <td/>
            <td>Width</td>
            <td>15000</td>
         </tr>
         <tr>
            <td/>
            <td/>
            <td>Height</td>
            <td>10000</td>
         </tr>
         <tr bgcolor="#ffff00">
            <td> Sensor: Sensor</td>
            <td>2</td>
            <td/>
            <td/>
         </tr>
         <tr>
            <td/>
            <td/>
            <td> Sensor: Name</td>
            <td>Pressure</td>
         </tr>
         <tr>
            <td/>
            <td/>
            <td> Sensor: Position</td>
            <td>222</td>
         </tr>
         <tr bgcolor="#00ffff">
            <td> Sector: Sector</td>
            <td>1</td>
            <td/>
            <td/>
         </tr>
         <tr>
            <td/>
            <td/>
            <td> Sector: Left</td>
            <td>100</td>
         </tr>
         <tr>
            <td/>
            <td/>
            <td> Sector: Right</td>
            <td>1000</td>
         </tr>
         <tr>
            <td/>
            <td/>
            <td> Sector: Active</td>
            <td>1</td>
         </tr>
         <tr>
            <td/>
            <td/>
            <td> Sector: Name</td>
            <td>Begin</td>
         </tr>
         <tr bgcolor="#00ffff">
            <td> Sector: Sector</td>
            <td>2</td>
            <td/>
            <td/>
         </tr>
         <tr bgcolor="#ff0000">
            <td>Station</td>
            <td>2</td>
            <td/>
            <td/>
         </tr>
         <tr>
            <td/>
            <td/>
            <td>Name</td>
            <td>Mark</td>
         </tr>
         <tr>
            <td/>
            <td/>
            <td>Width</td>
            <td>12500</td>
         </tr>
         <tr>
            <td/>
            <td/>
            <td>Height</td>
            <td>20000</td>
         </tr>
         <tr bgcolor="#ffff00">
            <td> Sensor: Sensor</td>
            <td>2</td>
            <td/>
            <td/>
         </tr>
         <tr>
            <td/>
            <td/>
            <td> Sensor: Name</td>
            <td>Pressure</td>
         </tr>
         <tr>
            <td/>
            <td/>
            <td> Sensor: Position</td>
            <td>420</td>
         </tr>
         <tr bgcolor="#00ffff">
            <td> Sector: Sector</td>
            <td>1</td>
            <td/>
            <td/>
         </tr>
         <tr bgcolor="#00ffff">
            <td> Sector: Sector</td>
            <td>2</td>
            <td/>
            <td/>
         </tr>
         <tr>
            <td/>
            <td/>
            <td> Sector: Left</td>
            <td>15000</td>
         </tr>
         <tr>
            <td/>
            <td/>
            <td> Sector: Right</td>
            <td>15500</td>
         </tr>
         <tr>
            <td/>
            <td/>
            <td> Sector: Active</td>
            <td>1</td>
         </tr>
         <tr>
            <td/>
            <td/>
            <td> Sector: Name</td>
            <td>End</td>
         </tr>
      </table>
   </body>
</html>

我应该如何正确选择 Active Sector 的所有属性? 提前谢谢你。

【问题讨论】:

    标签: xml xslt xslt-1.0


    【解决方案1】:

    我认为主要的解决方法是将“Active”属性的检查移到名为“Sectortype”的模板中

    <xsl:template name="Sectortype">
      <xsl:for-each select="class[@type = 'Sector']"> 
        <tr bgcolor = "#00ffff">
          <td> Sector: <xsl:value-of select="@type"/> </td>
          <td> <xsl:value-of select="@id+1"/> </td>
          <td></td> 
          <td></td> 
        </tr>
        <xsl:if test="attribute[@name='Active']/@value='1'">
          <xsl:call-template name="Sectorname"/>
        </xsl:if>
      </xsl:for-each>
    </xsl:template>
    

    注意type 属性的测试如何成为xsl:for-each 的一部分,而不是单独的xsl:if 语句。

    然后,“Sectorname”模板将如下所示

    <xsl:template name="Sectorname">
      <xsl:for-each select="attribute">
        <tr>
          <td></td> 
          <td></td> 
          <td> Sector: <xsl:value-of select="@name"/></td>
          <td> <xsl:value-of select="@value"/></td>
        </tr>
      </xsl:for-each>
    </xsl:template>
    

    我会考虑简化 XSLT,因为您有三个相似的模板输出 attribute 元素,可以通过参数组合成一个。

    试试这个 XSLT

    <xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">  
      <xsl:output method="html" />
      <xsl:strip-space elements="*" />
    
      <xsl:template match = "/"> 
        <html>
          <style>
            table, th, td {
            border: 1px solid black;
            border-spacing: 0px;
            }
          </style>
          <body>
            <h2>Item</h2>
            <table>
              <!--xsl:apply-templates/> -->
              <tr bgcolor = "#9acd32">
                <th>Type</th>
                <th>ID</th>
                <th>Name</th>
                <th>Value</th>
              </tr>
              <xsl:apply-templates select="map"/>
            </table>
          </body> 
        </html> 
      </xsl:template>  
    
      <xsl:template match="class">
        <tr bgcolor = "#ff0000">
          <td> <xsl:value-of select="@type"/> </td> 
          <td> <xsl:value-of select="@id+1"/> </td> 
          <td></td> 
          <td></td> 
        </tr> 
        <xsl:apply-templates select="attribute"/>
        <xsl:call-template name="Sensortype"/>
        <xsl:call-template name="Sectortype"/>
      </xsl:template>
    
      <xsl:template match="attribute">
        <xsl:param name="prefix" />
        <tr>
          <td></td> 
          <td></td> 
          <td> 
            <xsl:if test="$prefix">
              <xsl:value-of select="concat($prefix, ': ')" />
            </xsl:if>
            <xsl:value-of select="@name"/>
          </td>
          <td> 
            <xsl:value-of select="@value"/>
          </td>
        </tr>
    
      </xsl:template>
    
      <xsl:template name="Sensortype">
        <xsl:for-each select="class[@type = 'Sensor']"> 
          <tr bgcolor = "#ffff00">
            <td> Sensor: <xsl:value-of select="@type"/> </td>
            <td> <xsl:value-of select="@id+1"/> </td>
            <td></td> 
            <td></td> 
          </tr> 
          <xsl:apply-templates select="attribute">
            <xsl:with-param name="prefix" select="'Sensor'" />
          </xsl:apply-templates>
        </xsl:for-each>
      </xsl:template>
    
      <xsl:template name="Sectortype">
        <xsl:for-each select="class[@type = 'Sector']"> 
          <tr bgcolor = "#00ffff">
            <td> Sector: <xsl:value-of select="@type"/> </td>
            <td> <xsl:value-of select="@id+1"/> </td>
            <td></td> 
            <td></td> 
          </tr>
          <xsl:if test="attribute[@name='Active']/@value='1'">
            <xsl:apply-templates select="attribute">
              <xsl:with-param name="prefix" select="'Sector'" />
            </xsl:apply-templates>
          </xsl:if>
        </xsl:for-each>
      </xsl:template>
    </xsl:stylesheet>
    

    还要注意,在这种情况下,匹配“map”的模板并不是真正需要的,因为 XSLT 的内置模板会处理这个问题。

    【讨论】:

    • 非常感谢。它完美地工作!另一个问题:我怎样才能获得一个表,每个站的参数在不同的列中,而不是在同一列中的站 0 后面的站 1 的解决方案?
    • 老实说,这可能很棘手。至少,在 cmets 中解释起来太棘手了,所以你可能想问一个全新的问题。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多