2013-03-29 25 views
3

我一直在嘗試使用XSLT解析.net配置文件(web.config/app.config)和然後執行不同的操作(如替換屬性和創建新元素),這一直很順利,但現在我一直試圖重新創建一個節點樹,以防其中一些或全部不存在。不幸的是,我還沒有得到這個工作。XSLT:解析.Net Web.Config並嘗試添加節點樹(如果它不存在)

我想知道如果有人能幫助我嗎?

實例的Web.config

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <appSettings> 
    <add key="webpages:Version" value="2.0.0.0" /> 
    <add key="webpages:Enabled" value="false" /> 
    <add key="setting1" value="true" /> 
    <add key="setting2" value="true" /> 
    <add key="setting3" value="true" /> 
    </appSettings> 
    <system.serviceModel> 
    <client> 
     <endpoint name="endpointName1" address="http://endpoint1/endpoint1Service.svc" binding="endpointServiceBinding" /> 
    </client> 
    </system.serviceModel> 
</configuration> 

我想使它這樣我可以在新的或其他節點,而不會干擾任何其他節點,並假設它不存在補充。

客戶端證書節點(XPath的?下方)

/configuration/system.serviceModel/behaviors/endpointBehaviors 
     /behavior[@name=service1BehaviorName]/clientCredentials/clientCertificate 

他是問題的一個簡化版本,如果你感到害怕的Web.config :)

<Node1> 
    <Node2> 
     <Node3 name="1" value="value1" /> 
     <Node3 name="2" value="value3" /> 
    </Node2> 
</Node1> 

我需要怎樣的信息執行以下步驟

  1. 創建節點2如果它不存在
  2. 下面的語句要麼
    • 創建一個新的節點3具有NAME = 「3」
    • 與NAME = 「2」

我可以寫出修改節點3的內容代碼中添加一個新的節點,但我真的不能弄清楚如何將它們連接起來

<!-- This should copy everything/be the the base rule --> 
<xsl:template name="CopyAll" match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<!-- This will check and see if node2 does not exist, and create it if it does not --> 
<xsl:template name="rule_1" match="/Node1"> 
    <xsl:copy> 
     <xsl:if test="not(/Node1/Node2)"> 
      <Node2> 
      <xsl:call-template name="rule_2"/> <!-- call rule 2 to create a node3 --> 
      </Node2> 
     </xsl:if> 
    </xsl:copy> 
    <xsl:apply-templates /> <!-- Not sure why this is here, but it seems to need to be here in order to keep copying the xml file--> 
</xsl:template> 

<!-- Add node3 if it doesn't exist --> 
<xsl:template name="rule_2" match="/Node1/Node2/"> 
    <xsl:if test="not(/Node1/Node2/Node3[@name=1/)> 
     <Node3 name="1" value="newValue" /> 
    </xsl:if> 
    <xsl:apply-templates /> <!-- Not sure why this is here, but it seems to need to be here in order to keep copying the xml file--> 
<xsl:template> 

<!-- Change the value of Node3 --> 
<xsl:template match="/Node1/Node2/node3[@name='1']"> 
<xsl:copy> 
    <!-- Blanket statement for keeping all attributes --> 
    <xsl:copy-of select ="@*" /> 
    <!-- Change the below attributes --> 
    <xsl:attribute name="value">newValue</xsl:attribute> 
    <xsl:apply-templates /><!-- Not sure why this is here, but it seems to need to be here in order to keep copying the xml file--> 
</xsl:copy> 
</xsl:template> 

編輯: 我有另外一個問題,但因爲我的origi最後的問題得到了解決,我繼續提出第一個答案作爲我的問題的答案。爲了公平對待Dimitre,他的解決方案也適用。

回答

4

這是一個比你原來的嘗試更清潔的方法。請記住,XPath是大小寫敏感的,node3是不一樣的Node3

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:exslt="http://exslt.org/common" 
       exclude-result-prefixes="exslt"> 
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:variable name="treeToAddNF"> 
    <Node2> 
     <Node3 name="1" value=""> 
     <Node4> 
      <Node5/> 
     </Node4> 
     </Node3> 
    </Node2> 
    </xsl:variable> 
    <xsl:variable name="treeToAdd" select="exslt:node-set($treeToAddNF)" /> 

    <xsl:template match="@*|node()" name="Copy"> 
    <xsl:param name="contentsToAdd" select="/.." /> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
     <xsl:apply-templates select="$contentsToAdd" /> 
    </xsl:copy> 
    </xsl:template> 

    <!-- Add Node2 to any Node1 that does not have a Node2 --> 
    <xsl:template match="Node1[not(Node2)]"> 
    <xsl:call-template name="Copy"> 
     <xsl:with-param name="contentsToAdd" select="$treeToAdd/Node2" /> 
    </xsl:call-template> 
    </xsl:template> 

    <!-- Add node3 if it doesn't exist --> 
    <xsl:template match="Node2[not(Node3/@name = 1)]"> 
    <xsl:call-template name="Copy"> 
     <xsl:with-param name="contentsToAdd" select="$treeToAdd/Node2/*" /> 
    </xsl:call-template> 
    </xsl:template> 

    <xsl:template match="Node3[@name = 1][not(Node4)]"> 
    <xsl:call-template name="Copy"> 
     <xsl:with-param name="contentsToAdd" select="$treeToAdd/Node2/Node3/*" /> 
    </xsl:call-template> 
    </xsl:template> 

    <xsl:template match="Node3[@name = 1]/Node4[not(Node5)]"> 
    <xsl:call-template name="Copy"> 
     <xsl:with-param name="contentsToAdd" select="$treeToAdd/Node2/Node3/Node4/*" /> 
    </xsl:call-template> 
    </xsl:template> 

    <xsl:template match="Node3[@name='1']/@value"> 
    <xsl:attribute name="value">newValue</xsl:attribute> 
    </xsl:template> 
</xsl:stylesheet> 

當此輸入運行:

<Node1> 

</Node1> 

結果是:

<Node1> 
    <Node2> 
    <Node3 name="1" value="newValue"> 
     <Node4> 
     <Node5 /> 
     </Node4> 
    </Node3> 
    </Node2> 
</Node1> 

當在此輸入上運行:

<Node1> 
    <Node2> 
    <Node3 name="2" value="value3" /> 
    </Node2> 
</Node1> 

結果是:

<Node1> 
    <Node2> 
    <Node3 name="2" value="value3" /> 
    <Node3 name="1" value="newValue"> 
     <Node4> 
     <Node5 /> 
     </Node4> 
    </Node3> 
    </Node2> 
</Node1> 

而當此輸入運行:

<Node1> 
    <Node2> 
    <Node3 name="1" value="value1" otherAttribute="7" /> 
    <Node3 name="2" value="value3" otherAttribute="9" /> 
    </Node2> 
</Node1> 

結果是:

<Node1> 
    <Node2> 
    <Node3 name="1" value="newValue" otherAttribute="7"> 
     <Node4> 
     <Node5 /> 
     </Node4> 
    </Node3> 
    <Node3 name="2" value="value3" otherAttribute="9" /> 
    </Node2> 
</Node1> 
+0

感謝您的幫助球員,無論或像你說的,他們將您的解決方案工作。我想,在我能繼續完成之前,我有最後一道障礙。在你的兩個解決方案中,如果它們不存在,你們已經對整棵樹進行了硬編碼。從上面看我的web.config例子,你會注意到我可能必須創建5到6個節點。因此,我正在尋找一種解決方案,我不需要那樣做。 – user1079703

+0

從上面 防爆繼續說道: 如果我重做您當前的答案來解決加入「節點2」,「節點3」,併發出「節點4」,他們將包含從「Node3」添加完整樹的方式,其中包含完整的「Node4」樹以及用完整的「Node4」文本添加「Node4」的方法。這當然會使得與「Node4」完全相同的文本會在XSLT中出現兩次。我不想兩次寫同樣的東西,所以在我重寫它的情況下,我只需要在一個位置更改它。謝謝 – user1079703

+0

我已經修改了上面的答案,以避免在XSLT中添加要複製的部分的副本。您會注意到'treeToAddNF'變量中的'value'屬性是空的,但這是有意的。處理該屬性的模板負責爲其提供正確的值,這也避免了XSLT中的重複。 – JLRishe

1

這裏是一個較短的溶液

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="Node1[not(Node2)]"> 
    <Node1> 
    <xsl:apply-templates select="@*|node()"/> 
     <Node2> 
     <Node3 name="1" value="newValue" /> 
     </Node2> 
    </Node1> 
</xsl:template> 

<xsl:template match="Node3[@name='1']"> 
    <Node3 value="newValue"> 
    <xsl:apply-templates select="@*[not(name()='value')]|node()"/> 
    </Node3> 
</xsl:template> 

<xsl:template match="Node2[not(Node3[@name='1'])]"> 
    <Node2> 
    <xsl:apply-templates select="@*| node()"/> 
    <Node3 name="1" value="newValue" /> 
    </Node2> 
</xsl:template> 
</xsl:stylesheet> 

當這個XML文檔上運行:

<Node1> 

</Node1> 

結果是

<Node1> 
    <Node2> 
    <Node3 name="1" value="newValue" /> 
    </Node2> 
</Node1> 

當這個XML文檔上運行:

<Node1> 
    <Node2> 
    <Node3 name="2" value="value3" /> 
    </Node2> 
</Node1> 

結果是

<Node1> 
    <Node2> 
    <Node3 name="2" value="value3" /> 
    <Node3 name="1" value="newValue" /> 
    </Node2>" 
</Node1> 

當這個XML文檔上運行:

<Node1> 
    <Node2> 
    <Node3 name="1" value="value1" /> 
    <Node3 name="2" value="value3" /> 
    </Node2> 
</Node1> 

結果是

<Node1> 
    <Node2> 
    <Node3 name="1" value="newValue" /> 
    <Node3 name="2" value="value3" /> 
    </Node2> 
</Node1> 

最後,當這個運行XML文件:

<Node1> 
    <Node2> 
    <Node3 name="1" value="value1" otherAttribute="7" /> 
    <Node3 name="2" value="value3" otherAttribute="9" /> 
    </Node2> 
</Node1> 

結果是

<Node1> 
    <Node2> 
     <Node3 value="newValue" name="1" otherAttribute="7"/> 
     <Node3 name="2" value="value3" otherAttribute="9"/> 
    </Node2> 
</Node1> 
+0

您的解決方案「非常短」,因爲它遺漏了功能。如果名稱爲1的Node3具有名稱和值以外的任何屬性或任何子元素,則它們將被您的解決方案取消。 – JLRishe

+0

@JLRishe,目前還不清楚OP是否需要這個。我調整了您指出的新案例的解決方案,解決方案仍然更短:) –

相關問題