0

我有一个 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>

以下是输入 XML:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>  
</configuration>
4

1 回答 1

0

即使您要应用这两个模板,它们也会输出一个配置元素,这将导致您的输出具有两个配置元素,而不仅仅是您需要的那个。

但是,如果您真的无法更改第一个模板,我可以想到一个相当老套的解决方案。

您可以做的是创建一个与文档元素匹配的模板,该模板位于根配置元素之上,因此将首先匹配

<xsl:template match="/">

然后,在此模板中,您可以应用他们的配置匹配模板,但将结果存储在变量中

 <xsl:variable name="theirs">
    <xsl:apply-templates select="configuration" />
 </xsl:variable>

我假设您在这里使用的是 Microsoft 平台,因为它非常像 Microsoft 应用程序配置文件。这意味着您应该可以访问 Microsoft 的扩展功能。您将需要这些,因为theirs变量是“结果树片段”,但要使此解决方案正常工作,您需要将其作为节点集进行访问。

本质上,您可以在自己的模板(现在匹配的模板/)中执行以下操作:

<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>
于 2013-06-27T19:14:39.473 回答