2013-06-27 9 views
0

Я трансформация XSLT показано ниже:преобразование 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> 
+1

Вы забыли показать входной XML. – Tomalak

+0

Извините, добавил вход xml. –

+0

У вас не может быть двух шаблонов, соответствующих одному и тому же узлу, и ожидать, что оба они будут запущены. Только один из них будет запущен ('' в вашем случае). Мой вопрос: Очевидно, вы * можете * изменить XSLT-файл и добавить свой собственный шаблон, так почему вы говорите, что не можете изменить другой шаблон? – Tomalak

ответ

0

Даже если вы должны были применить оба шаблоны, они оба выводит конфигурации элемента, который может привести к вашей продукции с двумя конфигурацией элементов , а не только тот, который вам нужен.

Однако я могу придумать довольно хакерское решение, если вы действительно не можете изменить первый шаблон.

Что вы могли бы сделать, это создать шаблон, соответствующий элемент документа, который является уровнем выше корня конфигурации элемента, и так будет соответствовать первой

<xsl:template match="/"> 

Затем в рамках этого шаблона, можно применить их шаблон соответствия конфигурации, но сохранить результат в переменной

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

я предполагаю, вы используете платформу Microsoft здесь, учитывая это очень много приложение конф Microsoft ation файл. Это означает, что вы должны иметь доступ к функциям расширения 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>