convert XSLT code from version 2.0 to 1.0

前端 未结 1 1599
攒了一身酷
攒了一身酷 2021-01-28 04:31

There is xslt code for version 2.0 which gives output shown below but I want to convert it to version 1.0. I referred following links.. How to compare two XML nodes and get comp

相关标签:
1条回答
  • 2021-01-28 04:32

    In the previous question it is mentioned about Muenchian Grouping, so you must be already aware this is the approach to take. In this case, you are grouping by the network name, which will form the basis of your table rows, so you define a key like this

    <xsl:key name="networks" match="w3:DataNodeBase" use="w3:Name"/>
    

    (The w3: prefix is used here because of namespaces. All your nodes in your XML are in the namespace "http://www.w3.org" and in XSLT 1.0 you will need to explicitly declare this)

    Also, you will need to check for distinct value of IP Address for each network later, so it is also worth defining a key to help doing this

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

    Note the | symbol here. It can be any character you choose, just as long as it doesn't occur in either Name or IPAddress)

    For getting the columns, which are your OperatorStation elements, the code is very much as before (with the main difference being about the namespace prefix)

    <xsl:variable name="allStations" select="//w3:OperatorStation"/>
    

    Outputting the columns is then much as before too

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

    The first main difference though is when you want to get the distinct networks, for your columns. This is where you use Muenchian Grouping

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

    Within the template that matches this, you can check for whether all IP addresses are the same by using the second key

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

    Outputing the IP addresses for the row, is then simply a case of looping over the stations, and outputting the one with the matching network

    <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>
    

    Note that the following expression would also work in this case

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

    Anyway, try this 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>
    

    EDIT: If you wish to restrict the entries to a certain family, in this case just add a condition to check the family to the two keys

    <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)"/>
    
    0 讨论(0)
提交回复
热议问题