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>

しかし、何らかの理由で機能していません。なぜ 2 つのテンプレートが一致するのかと尋ねられるかもしれません。問題は、サードパーティが提供する以下の上部セクションを変更できないことです。

<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

両方のテンプレートを適用したとしても、どちらも構成要素を出力するため、必要な構成要素だけでなく、2 つの構成要素が出力されることになります。

ただし、最初のテンプレートを本当に変更できない場合は、かなりハックな解決策を考えることができます。

あなたができることは、ルート構成要素の上のレベルであるドキュメント要素に一致するテンプレートを作成することです。したがって、最初に一致します

<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 に答える