下面的 XSLT 代码通过父节点比较结果为我提供了结果。我正在寻找子节点比较结果,预期结果如下所示。描述:XSLT 代码给出了父节点(网络 A、网络 B 等),我想要子节点(网络 AA、网络 AB 等)比较结果。我建议您检查输入xml文件和预期的输出,以轻松理解我的要求。请参考链接将XSLT代码从2.0版转换为1.0版
输入 XML 文件:
<?xml version="1.0" encoding="utf-8"?>
<OperatorStationCollection >
<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>
<ChildNodes>
<DataNodeChild xsi:type="SubResult">
<Family>NetworkSettings</Family>
<Name>Network AA</Name>
<IPAddress>111.11.11.12</IPAddress>
</DataNodeChild>
<DataNodeChild xsi:type="SubResult">
<Family>NetworkSettings</Family>
<Name>Network AB</Name>
<IPAddress>111.11.11.13</IPAddress>
</DataNodeChild>
</ChildNodes>
</DataNodeBase>
<DataNodeBase xsi:type="Adaptor">
<Family>NetworkSettings</Family>
<Name>Network B</Name>
<IPAddress>111.22.11.1</IPAddress>
<ChildNodes>
<DataNodeChild xsi:type="SubResult">
<Family>NetworkSettings</Family>
<Name>Network BA</Name>
<IPAddress>111.11.11.21</IPAddress>
</DataNodeChild>
<DataNodeChild xsi:type="SubResult">
<Family>NetworkSettings</Family>
<Name>Network BB</Name>
<IPAddress>111.11.11.31</IPAddress>
</DataNodeChild>
</ChildNodes>
</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>
<ChildNodes>
<DataNodeChild xsi:type="SubResult">
<Family>NetworkSettings</Family>
<Name>Network AA</Name>
<IPAddress>111.11.11.12</IPAddress>
</DataNodeChild>
<DataNodeChild xsi:type="SubResult">
<Family>NetworkSettings</Family>
<Name>Network AB</Name>
<IPAddress>111.11.11.13</IPAddress>
</DataNodeChild>
</ChildNodes>
</DataNodeBase>
<DataNodeBase xsi:type="Adaptor">
<Family>NetworkSettings</Family>
<Name>Network B</Name>
<IPAddress>111.22.11.1</IPAddress>
<ChildNodes>
<DataNodeChild xsi:type="SubResult">
<Family>NetworkSettings</Family>
<Name>Network BA</Name>
<IPAddress>111.11.11.12</IPAddress>
</DataNodeChild>
<DataNodeChild xsi:type="SubResult">
<Family>NetworkSettings</Family>
<Name>Network BB</Name>
<IPAddress>111.11.11.13</IPAddress>
</DataNodeChild>
</ChildNodes>
</DataNodeBase>
</Nodes>
</OperatorStation>
</OperatorStationCollection>
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>
预期输出:由于没有添加表格的规定,我已经为结果制作了 hatml 代码,请将此代码保存到 html 文件并查看预期的输出。为了理解我已经制作了表格,我正在寻找 xml 的输出,但如果有人制作以表格格式给出/显示结果的 xslt 文件,那就太好了。
<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>
</tr>
<tr>
<td>Network AB</td><td>Equal</td><td>111.11.11.12</td><td>111.11.11.12</td>
</tr>
<tr>
<td>Network AB</td><td>Equal</td><td>111.11.11.13</td><td>111.11.11.13</td>
</tr>
<tr>
<td>Network BA</td><td>Unequal</td><td>111.11.11.21</td><td>111.11.11.12</td>
</tr>
<tr>
<td>Network BB</td><td>Unequal</td><td>111.11.11.31</td><td>111.11.11.13</td>
</tr>
</table>
</body>
</html>
在回答之前,我假设您错过了 XML 中的命名空间声明,并且根元素实际上应该如下所示(如果没有,您还需要从 XSLT 中删除命名空间的所有跟踪)
<OperatorStationCollection xmlns="http://www.w3.org">
在上一个问题中,您是按 DataNodeBase 分组的,但在新问题中,您是按 DataNodeChild 分组的。这意味着您真正需要做的就是在XSLT中用DataNodeChild替换所有出现的DataNodeBase。
唯一要进行的其他更改是此行
<xsl:value-of
select="key('networks', $network)[../../w3:Name=current()/w3:Name]/w3:IPAddress"/>
由于 DataNodeChild 嵌套了另外两个级别,因此必须相应地更改表达式
<xsl:value-of
select="key('networks', $network)[../../../../w3:Name=current()/w3:Name]/w3:IPAddress"/>
更好的是,在任何级别上应对它,它可能是这个
<xsl:value-of
select="key('networks', $network)[ancestor::w3:OperatorStation/w3:Name=current()/w3:Name]/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:DataNodeChild" use="w3:Name"/>
<xsl:key name="networksAndIP" match="w3:DataNodeChild" 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:DataNodeChild[generate-id() = generate-id(key('networks', w3:Name)[1])]"/>
</table>
</xsl:template>
<xsl:template match="w3:DataNodeChild">
<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)[ancestor::w3:OperatorStation/w3:Name=current()/w3:Name]/w3:IPAddress"/>
</td>
</xsl:for-each>
</tr>
</xsl:template>
</xsl:stylesheet>