将XSLT代码从2.0版转换为1.0版

将XSLT代码从2.0版转换为1.0版,xslt,Xslt,2.0版的xslt代码给出了如下所示的输出,但我想将其转换为1.0版。 我参考了以下链接。。 及 输入XML文件: <?xml version="1.0" encoding="utf-8"?> <OperatorStationCollection xmlns="http://www.w3.org" > <OperatorStation xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://ww

2.0版的xslt代码给出了如下所示的输出,但我想将其转换为1.0版。 我参考了以下链接。。 及

输入XML文件:

<?xml version="1.0" encoding="utf-8"?>
<OperatorStationCollection xmlns="http://www.w3.org" >
<OperatorStation xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Name>OS001</Name>
    <Nodes>
      <DataNodeBase xsi:type="Adaptor">
        <Family>NetworkSettings</Family>
        <Name>Network A</Name>  
        <IPAddress>111.11.11.1</IPAddress>        
      </DataNodeBase>
      <DataNodeBase xsi:type="Adaptor">
        <Family>Network1111</Family>
        <Name>Network B</Name>                
        <IPAddress>111.22.11.1</IPAddress>          
      </DataNodeBase>
      <DataNodeBase xsi:type="Adaptor">
        <Family>Network2222</Family>
        <Name>Network C</Name>
        <IPAddress>111.33.11.1</IPAddress>
      </DataNodeBase>
      </Nodes>   
  </OperatorStation>      
<OperatorStation xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Name>OS002</Name>
  <Nodes>
    <DataNodeBase xsi:type="Adaptor">
      <Family>NetworkSettings</Family>
      <Name>Network A</Name>
      <IPAddress>111.11.11.1</IPAddress>
    </DataNodeBase>
    <DataNodeBase xsi:type="Adaptor">
      <Family>Network1111</Family>
      <Name>Network B</Name>
      <IPAddress>111.22.11.2</IPAddress>
    </DataNodeBase>
    <DataNodeBase xsi:type="Adaptor">
      <Family>NetworkSettings</Family>
      <Name>Network D</Name>
      <IPAddress>111.33.11.2</IPAddress>
    </DataNodeBase>
  </Nodes>
</OperatorStation>
  <OperatorStation xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Name>OS003</Name>
    <Nodes>
      <DataNodeBase xsi:type="Adaptor">
        <Family>NetworkSettings</Family>
        <Name>Network A</Name>
        <IPAddress>111.11.11.1</IPAddress>
      </DataNodeBase>
      <DataNodeBase xsi:type="Adaptor">
        <Family>NetworkSettings</Family>
        <Name>Network B</Name>
        <IPAddress>111.22.11.3</IPAddress>
      </DataNodeBase>
      <DataNodeBase xsi:type="Adaptor">
        <Family>NetworkSettings</Family>
        <Name>Network E</Name>
        <IPAddress>111.33.11.3</IPAddress>
      </DataNodeBase>
    </Nodes>
  </OperatorStation>
</OperatorStationCollection>

OS001
网络设置
网络A
111.11.11.1        
网络1111
网络B
111.22.11.1          
网络2222
网络C
111.33.11.1
OS002
网络设置
网络A
111.11.11.1
网络1111
网络B
111.22.11.2
网络设置
网络D
111.33.11.2
OS003
网络设置
网络A
111.11.11.1
网络设置
网络B
111.22.11.3
网络设置
网络E
111.33.11.3
2.0版的XSLT代码:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
      <xsl:template match="/">
        <xsl:variable name="allStations"
                      select="/*:OperatorStationCollection/*:OperatorStation" />
        <table>
          <!-- Header row - two fixed columns plus one per station name -->
          <tr>
            <td>Name</td><td>Status</td>
            <xsl:for-each select="$allStations">
              <td><xsl:value-of select="*:Name" /></td>
            </xsl:for-each>
          </tr>
          <!-- main rows - one per "group" of DataNodeBase elements which share the
               same Name -->
          <xsl:for-each-group
              select="$allStations/*:Nodes/*:DataNodeBase"
              group-by="*:Name">
            <!-- calculate the column values - the IPAddress if this network (i.e. the
                 current-group) has an entry for this station, and "None" if not -->
            <xsl:variable name="addresses"
                select="for $s in ($allStations)
                        return (current-group()[../.. is $s]/*:IPAddress, 'None')[1]" />
            <tr>
              <td><xsl:value-of select="current-grouping-key()" /></td>
              <td>
                <!-- equal if all the $addresses are the same, unequal otherwise -->
                <xsl:value-of select="if (count(distinct-values($addresses)) = 1)
                                      then 'Equal' else 'Unequal'" />
              </td>
              <xsl:for-each select="$addresses">
                <td><xsl:value-of select="."/></td>
              </xsl:for-each>
            </tr>
          </xsl:for-each-group>
        </table>
      </xsl:template>
    </xsl:stylesheet> 

名称状态
预期输出:由于并没有添加表的规定,我已经为结果生成了hatml代码,请将此代码保存到html文件中并查看预期输出

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>    
</head>
<body>

   <table>
            <tr>
            <td>Name</td><td>Status</td><td>OS01</td><td>OS02</td><td>OS03</td>
            </tr>
            <tr>
            <td>Network A</td><td>Equal</td><td>111.11.11.1</td><td>111.11.11.1</td><td>111.11.11.1</td>
            </tr>
            <tr>
            <td>Network B</td><td>Unequal</td><td>111.22.11.1</td><td>111.22.11.2</td><td>111.22.11.2</td>
            </tr>
            <tr>
            <td>Network C</td><td>Unequal</td><td>111.33.11.1</td><td>Not Exist</td><td>Not Exist</td>
            </tr>
            <tr>
            <td>Network D</td><td>Unequal</td><td>Not Exist</td><td>111.33.11.2</td><td>Not Exist</td>
            </tr>
            <tr>
            <td>Network E</td><td>Unequal</td><td>Not Exist</td><td>Not Exist</td><td>111.33.11.3</td>
            </tr>           
            </table>

</body>
</html>

名称StatusOS01OS02OS03
网络AEqual111.11.11.1111.11.11.1111.11.11.1
网络BUnequal111.22.11.1111.22.11.2111.22.11.2
网络CUnequal111.33.11.1不存在不存在
网络不存在111.33.11.2不存在
网络EUNEQUALN不存在不存在111.33.11.3

在上一个问题中提到了明钦族的分组,因此您必须已经意识到这是要采取的方法。在本例中,您是按网络名称分组的,网络名称将构成表行的基础,因此您可以定义如下键

<xsl:key name="networks" match="w3:DataNodeBase" use="w3:Name"/>
输出列也和以前一样

        <xsl:for-each select="$allStations">
           <td>
              <xsl:value-of select="w3:Name"/>
           </td>
        </xsl:for-each>

不过,第一个主要区别是,当您想要为您的专栏获取不同的网络时。这就是使用明钦族分组的地方

<xsl:apply-templates 
     select="//w3:DataNodeBase
              [generate-id() = generate-id(key('networks', w3:Name)[1])]" />

在与此匹配的模板中,可以使用第二个密钥检查所有IP地址是否相同

<xsl:choose>
    <xsl:when test="count(key('networksAndIP', concat(w3:Name, '|', w3:IPAddress))) = $allStationsCount">Equal</xsl:when>
    <xsl:otherwise>Unequal</xsl:otherwise>
</xsl:choose>

相等的
不等
然后,输出该行的IP地址就是在站点上循环,并用匹配的网络输出IP地址

<xsl:variable name="network" select="w3:Name"/>
<xsl:for-each select="$allStations">
   <td>
      <xsl:value-of select="key('networks', $network)[../../w3:Name=current()/w3:Name]/w3:IPAddress"/>
   </td>
</xsl:for-each>

请注意,以下表达式在这种情况下也适用

<xsl:value-of select="w3:Nodes/w3:DataNodeBase[w3:Name=$network]/w3:IPAddress"/>

无论如何,试试这个XSLT

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

   <xsl:key name="networks" match="w3:DataNodeBase" use="w3:Name"/>
   <xsl:key name="networksAndIP" match="w3:DataNodeBase" use="concat(w3:Name, '|', w3:IPAddress)"/>

   <xsl:variable name="allStations" select="//w3:OperatorStation"/>
   <xsl:variable name="allStationsCount" select="count($allStations)"/>

   <xsl:template match="/">
      <table><!-- Header row - two fixed columns plus one per station name -->
         <tr>
            <td>Name</td>
            <td>Status</td>
            <xsl:for-each select="$allStations">
               <td>
                  <xsl:value-of select="w3:Name"/>
               </td>
            </xsl:for-each>
         </tr>
         <xsl:apply-templates select="//w3:DataNodeBase[generate-id() = generate-id(key('networks', w3:Name)[1])]"/>
      </table>
   </xsl:template>

   <xsl:template match="w3:DataNodeBase">
      <tr>
         <td>
            <xsl:value-of select="w3:Name"/>
         </td>
         <td>
            <xsl:choose>
               <xsl:when test="count(key('networksAndIP', concat(w3:Name, '|', w3:IPAddress))) = $allStationsCount">Equal</xsl:when>
               <xsl:otherwise>Unequal</xsl:otherwise>
            </xsl:choose>
         </td>
         <xsl:variable name="network" select="w3:Name"/>
         <xsl:for-each select="$allStations">
            <td>
               <xsl:value-of select="key('networks', $network)[../../w3:Name=current()/w3:Name]/w3:IPAddress"/>
            </td>
         </xsl:for-each>
      </tr>
   </xsl:template>
</xsl:stylesheet>

名称
地位
相等的
不等
编辑:如果希望将条目限制到某个族,在这种情况下,只需添加一个条件,将该族检查到两个关键点即可

<xsl:key name="networks" match="w3:DataNodeBase[w3:Family='NetworkSettings']" use="w3:Name"/>
<xsl:key name="networksAndIP" match="w3:DataNodeBase[w3:Family='NetworkSettings']" use="concat(w3:Name, '|', w3:IPAddress)"/>


+1,恭喜你给出了这个非常完整的答案!我正在写一个答案,但我无法超越这个详细的解释它的作品,感谢所有这些解释和完美的答案,这将有助于我今后的参考。这个答案我给你5*。@Tim,如果我只想要特定的家庭数据,假设我只想要“NetworkSettings”家庭数据,而不是其他家庭数据,因为还有很多其他家庭数据。我们如何使用此解决方案实现它?为了方便起见,我对输入xml文件进行了更改。等待回复…谢谢我修改了我的答案,希望能说明这一点,尽管我不完全清楚你期望的结果是什么。不过,为了便于将来参考,最好不要在回答问题后更改您的要求。你真的应该问一个全新的问题。谢谢。最初的XSLT2.0样式表是,在我意识到有人提出这个问题之前,我添加了一个XSLT1.0等价于这个答案。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:w3="http://www.w3.org">
   <xsl:output method="html" indent="yes"/>

   <xsl:key name="networks" match="w3:DataNodeBase" use="w3:Name"/>
   <xsl:key name="networksAndIP" match="w3:DataNodeBase" use="concat(w3:Name, '|', w3:IPAddress)"/>

   <xsl:variable name="allStations" select="//w3:OperatorStation"/>
   <xsl:variable name="allStationsCount" select="count($allStations)"/>

   <xsl:template match="/">
      <table><!-- Header row - two fixed columns plus one per station name -->
         <tr>
            <td>Name</td>
            <td>Status</td>
            <xsl:for-each select="$allStations">
               <td>
                  <xsl:value-of select="w3:Name"/>
               </td>
            </xsl:for-each>
         </tr>
         <xsl:apply-templates select="//w3:DataNodeBase[generate-id() = generate-id(key('networks', w3:Name)[1])]"/>
      </table>
   </xsl:template>

   <xsl:template match="w3:DataNodeBase">
      <tr>
         <td>
            <xsl:value-of select="w3:Name"/>
         </td>
         <td>
            <xsl:choose>
               <xsl:when test="count(key('networksAndIP', concat(w3:Name, '|', w3:IPAddress))) = $allStationsCount">Equal</xsl:when>
               <xsl:otherwise>Unequal</xsl:otherwise>
            </xsl:choose>
         </td>
         <xsl:variable name="network" select="w3:Name"/>
         <xsl:for-each select="$allStations">
            <td>
               <xsl:value-of select="key('networks', $network)[../../w3:Name=current()/w3:Name]/w3:IPAddress"/>
            </td>
         </xsl:for-each>
      </tr>
   </xsl:template>
</xsl:stylesheet>
<xsl:key name="networks" match="w3:DataNodeBase[w3:Family='NetworkSettings']" use="w3:Name"/>
<xsl:key name="networksAndIP" match="w3:DataNodeBase[w3:Family='NetworkSettings']" use="concat(w3:Name, '|', w3:IPAddress)"/>