我有一个如下所示的XSLT转换:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/configuration">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
<xsl:element name="system.diagnostics">
<trace autoflush="true">
<listeners>
<add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics" name="AzureDiagnostics"></add>
</listeners>
</trace>
</xsl:element>
</xsl:copy>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="configuration">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
<xsl:element name="location">
<xsl:attribute name="path">securfolder1</xsl:attribute>
<system.web>
<authorization>
<deny users="*"/>
</authorization>
</system.web>
</xsl:element>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我期待上面应该产生以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.diagnostics>
<trace autoflush="true">
<listeners>
<add name="AzureDiagnostics"
type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics"/>
</listeners>
</trace>
</system.diagnostics>
<location path="securfolder1">
<system.web>
<authorization>
<deny users="*"/>
</authorization>
</system.web>
</location>
</configuration>
但是有些原因它没有用。您可能会问为什么我有两个模板匹配。问题是由第三方提供的以下顶部我们无法改变。
<xsl:template match="/configuration">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
<xsl:element name="system.diagnostics">
<trace autoflush="true">
<listeners>
<add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics" name="AzureDiagnostics"></add>
</listeners>
</trace>
</xsl:element>
</xsl:copy>
</xsl:template>
以下是INPUT XML:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
</configuration>
答案 0 :(得分:0)
即使您要应用这两个模板,它们都会输出配置元素,这会导致您的输出有两个配置元素,而不仅仅是您的需要。
然而,我可以想到一个相当hacky的解决方案,如果你真的,真的不能让第一个模板改变。
您可以做的是创建一个与文档元素匹配的模板,该模板元素高于根配置元素,因此将首先匹配
<xsl:template match="/">
然后,在此模板中,您可以应用其配置匹配模板,但将结果存储在变量
中 <xsl:variable name="theirs">
<xsl:apply-templates select="configuration" />
</xsl:variable>
我假设您在这里使用的是Microsoft平台,因为它非常适用于Microsoft应用程序配置文件。这意味着您应该可以访问Microsoft的扩展功能。您将需要这些,因为他们的变量是“结果树片段”,但要使此解决方案起作用,您需要将其作为节点集进行访问。
基本上,您可以在自己的模板(现在匹配/
)中执行的操作是:
<configuration>
<xsl:copy-of select="msxsl:node-set($theirs)/configuration/*" />
<!-- You own elements -->
</configuration>
换句话说,复制第一个模板生成的元素,然后输出自己的元素。
这是完整的XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/configuration">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<xsl:element name="system.diagnostics">
<trace autoflush="true">
<listeners>
<add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics" name="AzureDiagnostics"/>
</listeners>
</trace>
</xsl:element>
</xsl:copy>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:variable name="theirs">
<xsl:apply-templates select="configuration" />
</xsl:variable>
<configuration>
<xsl:copy-of select="msxsl:node-set($theirs)/configuration/*"/>
<xsl:element name="location">
<xsl:attribute name="path">securfolder1</xsl:attribute>
<system.web>
<authorization>
<deny users="*"/>
</authorization>
</system.web>
</xsl:element>
</configuration>
</xsl:template>
</xsl:stylesheet>
当应用于输入XML时,输出以下内容
<configuration>
<system.diagnostics>
<trace autoflush="true">
<listeners>
<add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics" name="AzureDiagnostics"/>
</listeners>
</trace>
</system.diagnostics>
<location path="securfolder1">
<system.web>
<authorization>
<deny users="*"/>
</authorization>
</system.web>
</location>
</configuration>