XSLT:解析.Net Web.Config并尝试添加Node树(如果它不存在)

时间:2013-03-29 17:22:05

标签: xslt configuration

我一直在尝试使用XSLT解析.net配置文件(web.config / app.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. 创建Node2(如果它不存在)
  2. 以下任何一项陈述
    • 创建一个名为“3”
    • 的新Node3
    • 使用name =“2”
    • 修改Node3的内容
  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>
    

    编辑: 我有另一个问题,但是由于我的原始问题已经解决,我继续将第一个答案标记为我的问题的答案。为了公平对待Dimitre,他的解决方案也有效。

2 个答案:

答案 0 :(得分:4)

这是一种比原始尝试更简洁的方法。请记住,XPath区分大小写,node3Node3不同:

<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>

答案 1 :(得分: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>