给出以下XML:
<interface name="Serial1/0"/>
<interface name="Serial2/0.0"/>
<interface name="Serial2/0.1"/>
<interface name="Serial3/0:0"/>
<interface name="Serial3/0:1"/>
我正在尝试生成以下输出:
<interface name="Serial1/0">
<unit name="Serial1/0"/>
</interface>
<interface name="Serial2/0">
<unit name="Serial2/0.0"/>
<unit name="Serial2/0.1"/>
</interface>
<interface name="Serial3/0">
<unit name="Serial3/0:0"/>
<unit name="Serial3/0:1"/>
</interface>
我创建了以下用于拆分字符串的函数:
<xsl:template name="getPhysicalInterfaceName">
<xsl:param name="interfaceName"/>
<xsl:choose>
<xsl:when test="contains($interfaceName, ':')">
<xsl:value-of select="substring-before($interfaceName, ':')"/>
</xsl:when>
<xsl:when test="contains($interfaceName, '.')">
<xsl:value-of select="substring-before($interfaceName, '.')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$interfaceName"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
我找到了使用xsl:key元素的引用,但是我没有看到在上下文中使用它的明显方法。任何的想法? (我正在使用xsltproc(XSLT1.0)进行转换。)
答案 0 :(得分:2)
XSLT 1.0:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:key
name = "kInterfaceByName"
match = "interface"
use = "
substring-before(concat(
substring-before(concat(@name, ':'), ':'),
'.'), '.')
"
/>
<xsl:template match="i">
<xsl:copy>
<xsl:apply-templates mode="group" select="interface" />
</xsl:copy>
</xsl:template>
<xsl:template match="interface" mode="group">
<xsl:variable name="name" select="
substring-before(concat(
substring-before(concat(@name, ':'), ':'),
'.'), '.')
" />
<xsl:variable name="interfaces" select="key('kInterfaceByName', $name)" />
<!-- Muenchian step -->
<xsl:if test="generate-id()=generate-id($interfaces[1])">
<interface name="{$name}">
<xsl:apply-templates mode="unit" select="$interfaces" />
</interface>
</xsl:if>
</xsl:template>
<xsl:template match="interface" mode="unit">
<unit name="{@name}" />
</xsl:template>
</xsl:stylesheet>
应用于
<i>
<interface name="Serial1/0"/>
<interface name="Serial2/0.0"/>
<interface name="Serial2/0.1"/>
<interface name="Serial3/0:0"/>
<interface name="Serial3/0:1"/>
</i>
结果
<i>
<interface name="Serial1/0">
<unit name="Serial1/0" />
</interface>
<interface name="Serial2/0">
<unit name="Serial2/0.0" />
<unit name="Serial2/0.1" />
</interface>
<interface name="Serial3/0">
<unit name="Serial3/0:0" />
<unit name="Serial3/0:1" />
</interface>
</i>
XPath表达式取代了您的getPhysicalInterfaceName
模板。
对'Serial2/0.0'
和'Serial3/0:1'
的示例:
':'
(=&gt; 'Serial2/0.0:'
; 'Serial3/0:1:'
)':'
(=&gt; 'Serial2/0.0'
; 'Serial3/0'
)'.'
(=&gt; 'Serial2/0.0.'
; 'Serial3/0.'
)'.'
(=&gt; 'Serial2/0'
; 'Serial3/0'
)编辑:简化的XPath表达式。我的第一次尝试工作但更复杂:
concat(
substring-before(@name, '/'),
'/',
substring-before(
concat(
translate(substring-after(@name, '/'), '.', ':'), ':'
),
':'
)
)
在正面,上面的表达式正确处理名称第一部分中的冒号和点,例如'Some.Serial3/0:1'
。较短的没有。如果您希望名称中有点,请使用更长的表达式。对它的解释是在revision history of this post。
答案 1 :(得分:1)
您应该查看Muenchian method以对XML项目进行分组。