我仍在学习 XSLT,但我不知道如何解决这个问题:
由
</result>
创建的结束标签 xsltproc
仍然缩进,就好像它是元素的一部分一样;例如:
<result>
<channel>netgroup_home_hosts</channel>
<value>0.006</value>
<!--thresholds start--><LimitMaxWarning>1</LimitMaxWarning><LimitMaxError>2</LimitMaxError><!--thresholds end-->
<!--range: min="0"-->
</result>
但是我希望结束标签与开始标签对齐。 要么是我忘记了什么,要么是我没有正确使用 XSLT(额外的注释是一些调试遗留下来的)。
这是一个(简单的)示例输入:
<?xml version="1.0" encoding="utf-8"?>
<MonitoringOutput id="id-13951" version="0.1">
<description>input</description>
<exit_code>0</exit_code>
<status_string>OK</status_string>
<info_string>response_time(netgroup:home_hosts) is 0.006 (0)</info_string>
<perf_string> netgroup_home_hosts=0.006;1;2;0</perf_string>
<perf_data count="1">
<sample label="netgroup_home_hosts">
<label>netgroup_home_hosts</label>
<value>0.006</value>
<thresholds>
<warn end="1"/>
<crit end="2"/>
</thresholds>
<range min="0"/>
</sample>
</perf_data>
</MonitoringOutput>
这是创建的输出(注释是为了帮助我调试 XSLT):
<?xml version="1.0" encoding="UTF-8"?>
<!--MonitoringOutput v0.1 id=id-13951 (PRTG.xsl v0.0.0)-->
<prtg>
<!--status_string=OK-->
<!--success status!-->
<!--perf_data:-->
<!--Description: input-->
<!--Exit Code: 0-->
<text>OK</text>
<!--Info String: response_time(netgroup:home_hosts) is 0.006 (0)-->
<!--Perf String: netgroup_home_hosts=0.006;1;2;0-->
<result>
<channel>netgroup_home_hosts</channel>
<value>0.006</value>
<!--thresholds start--><LimitMaxWarning>1</LimitMaxWarning><LimitMaxError\
>2</LimitMaxError><!--thresholds end-->
<!--range: min="0"-->
</result>
</prtg>
这就是 XSLT(可能过于复杂,但我想先把它做好,然后再优化):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/MonitoringOutput[@version]">
<xsl:comment><xsl:value-of select="name(.)"
/> v<xsl:value-of select="@version" /> id=<xsl:value-of select="@id"
/> (PRTG.xsl v0.0.0)</xsl:comment>
<xsl:variable name="main.node" select="." />
<prtg>
<xsl:comment>status_string=<xsl:value-of
select="$main.node/status_string" /> </xsl:comment>
<xsl:choose>
<xsl:when test="perf_data[@count > 0]">
<xsl:choose>
<xsl:when test="$main.node/perf_data/crit_labels[@count > 0]">
<xsl:comment>critical status!</xsl:comment>
</xsl:when>
<xsl:when test="$main.node/perf_data/warn_labels[@count > 0]">
<xsl:comment>warnings status!</xsl:comment>
</xsl:when>
<xsl:otherwise>
<xsl:comment>success status!</xsl:comment>
</xsl:otherwise>
</xsl:choose>
<xsl:apply-templates select="$main.node/perf_data"/>
</xsl:when>
<xsl:otherwise>
<error>1</error>
<xsl:comment>(<xsl:value-of select="$main.node/exit_code"
/>)</xsl:comment>
<text><xsl:value-of select="$main.node/info_string" /></text>
</xsl:otherwise>
</xsl:choose>
</prtg>
</xsl:template>
<xsl:template match="perf_data[@count > 0]">
<!-- no parsing error -->
<xsl:variable name="main.node" select=".." />
<xsl:variable name="perf.node" select="." />
<xsl:comment><xsl:value-of select="name(.)" />:</xsl:comment>
<!-- HOW TO? -->
<xsl:comment>Description: <xsl:value-of select="$main.node/description"
/></xsl:comment>
<xsl:comment>Exit Code: <xsl:value-of select="$main.node/exit_code"
/></xsl:comment>
<text><xsl:value-of select="$main.node/status_string" /></text>
<xsl:comment>Info String: <xsl:value-of select="$main.node/info_string"
/></xsl:comment>
<xsl:comment>Perf String: <xsl:value-of select="$main.node/perf_string"
/></xsl:comment>
<xsl:apply-templates select="$perf.node/sample"/>
</xsl:template>
<xsl:template match="perf_data/sample[@label]">
<result>
<xsl:apply-templates />
<xsl:variable name="is_crit" select="//crit_labels/name/text() = @label" />
<xsl:variable name="is_warn" select="//warn_labels/name/text() = @label" />
<xsl:choose>
<xsl:when test="$is_crit">
<warning>1</warning><xsl:comment>critical!</xsl:comment>
</xsl:when>
<xsl:when test="$is_warn">
<warning>1</warning>
</xsl:when>
</xsl:choose>
</result>
</xsl:template>
<xsl:template match="sample/label">
<channel><xsl:value-of select="."/></channel>
</xsl:template>
<xsl:template match="sample/range[@*]">
<xsl:for-each select="@*">
<xsl:comment>range: <xsl:value-of select="name(.)" />="<xsl:value-of
select="."/>"</xsl:comment>
</xsl:for-each>
</xsl:template>
<xsl:template match="sample/unit">
<CustomUnit><xsl:value-of select="."/></CustomUnit>
</xsl:template>
<xsl:template match="sample/value">
<value><xsl:value-of select="."/></value>
</xsl:template>
<xsl:template match="sample/thresholds">
<xsl:variable name="thresholds.node" select="." />
<xsl:comment><xsl:value-of select="name(.)" /> start</xsl:comment>
<xsl:apply-templates select="$thresholds.node/*"/>
<xsl:comment><xsl:value-of select="name(.)" /> end</xsl:comment>
</xsl:template>
<xsl:template match="thresholds/crit[@*]">
<xsl:for-each select="@*">
<xsl:variable name="attr.name" select="name(.)" />
<xsl:choose>
<xsl:when test="$attr.name = 'start'">
<LimitMinError><xsl:value-of select="." /></LimitMinError>
</xsl:when>
<xsl:when test="$attr.name = 'end'">
<LimitMaxError><xsl:value-of select="." /></LimitMaxError>
</xsl:when>
<xsl:otherwise>
<xsl:comment><xsl:value-of select="$attr.name" />="<xsl:value-of
select="." />"</xsl:comment>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<xsl:template match="thresholds/warn[@*]">
<xsl:for-each select="@*">
<xsl:variable name="attr.name" select="name(.)" />
<xsl:choose>
<xsl:when test="$attr.name = 'start'">
<LimitMinWarning><xsl:value-of select="." /></LimitMinWarning>
</xsl:when>
<xsl:when test="$attr.name = 'end'">
<LimitMaxWarning><xsl:value-of select="." /></LimitMaxWarning>
</xsl:when>
<xsl:otherwise>
<xsl:comment><xsl:value-of select="$attr.name" />="<xsl:value-of
select="." />"</xsl:comment>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
FWIW,如果添加以下内容,缩进似乎是正确的:
<xsl:strip-space elements="*"/>
到样式表的顶层。显然,在某些时候,您将模板应用于输入的文本节点,这会导致仅空白节点被复制到输出。但我不打算在你的 137 行代码中寻找它。