如何使用MSDeploy Parameters.xml文件更改名称空间中的XML元素?

问题描述:

我无法通过MSDeploy更改Web.config中的元素。我的parameters.xml文件:如何使用MSDeploy Parameters.xml文件更改名称空间中的XML元素?

<parameterEntry 
    kind="XmlFile" 
    scope="\\web.config$" 
    match="//spring/objects/object[@id='CultureResolver']/@type" /> 

相关部分的Web.config

<spring> 
    <objects xmlns="http://www.springframework.net"> 

     <object id="CultureResolver" type="Spring.Globalization.Resolvers.SessionCultureResolver, Spring.Web"> 
      <!--configure for server--> 
      <property name="DefaultCulture" value="en" /> 
     </object> 
    </objects> 
</spring> 

问题是<objects/>元素上的名称空间声明。您的XPath查询没有匹配,因为没有<objects/>元素具有空名称空间(这是查询所查找的内容)。

现在,XPath的指定XML命名空间是一个棘手的问题(在这种情况下,它甚至是不可能的),那么我建议你使用这个表达式来代替:

"//spring/*/*[@id='CultureResolver']/@type" 

HTH ...

+0

非常感谢,对我也有效!对于那些使用Google搜索:与部署parameters.xml和Mvc.Sitemap相同的问题。由于mvcSiteMap节点中的xmlns,IIS导入无法像这样匹配xpath:“/ mvcSiteMap/mvcSiteMapNode/mvcSiteMapNode [@ title ='My Title']/@ url”。 – Kirill 2014-09-26 12:42:54

+0

您的解决方法绝对奏效,我在第一次找到您的答案时向您致敬,但最近我发现您错了,无法正确编写指定XML名称空间的XPath查询,并且以Web部署支持。 – 2015-01-24 19:15:46

XPath技巧

你的例子有点棘手(起初)。但是,这XPath查询,而更长的时间,应该工作:

//spring/*[local-name() = 'objects' and namespace-uri() = 'http://www.springframework.net']/*[@id='CultureResolver' and local-name() = 'object' and namespace-uri() = 'http://www.springframework.net']/@type 

this answer所发现的这一招太问题c# - Declare namespaces within XPath expression,但我却发现它后,我已经张贴了这个答案(原本)。

我已经在下面留下了大部分原始答案,并且还添加了有关我的原始答案错误的额外部分。

我的例子

我想为NLog做到这一点;这里是我的NLog.config文件的例子:

<?xml version="1.0" encoding="utf-8" ?> 
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" throwExceptions="true"> 

    ... 

    <targets> 
    <target name="HipChat" xsi:type="MethodCall" className="DbNecromancer.Logging, DbNecromancer" methodName="SendHipChatRoomNotification"> 
     <parameter layout="1234567" name="roomId" /> 
     <parameter layout="blah-blah-blah" name="authToken" /> 
     <parameter layout="${message-layout}" name="message" /> 
     <parameter layout="${level}" name="nLogLevel" /> 
    </target> 
    </targets> 

    ... 
</nlog> 

下面是从我的parameters.xml文件相关的XPath查询更改parameter元素的layout属性与“roomId”的价值,为name属性:

/nlog/targets/target[@name='HipChat']/parameter[@name='roomId']/@layout

可以确认的是,上述的XPath不符合使用this free online XPath tester所需的属性。您也可以使用Web Deploy自身来确认它失败!

但我能得到这个工作,无论是在在线测试仪,并通过Web部署,而无需使用通配符或移除该命名空间声明NLog.config。诀窍是添加一个名称空间前缀。

以下是NLog中的修改行。配置

<nlog:nlog xmlns:nlog="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" throwExceptions="true"> 
    ... 
</nlog:nlog> 

下面是修改后的XPath查询:

/nlog:nlog/targets/target[@name='HipChat']/parameter[@name='roomId']/@layout 

你的榜样

我不能让你的榜样,只需添加一个前缀您的示例中的在线测试仪工作正在使用一个命名空间(并且我没有使用Spring的项目)。测试仪的输出,当我尝试只需添加一个前缀:

错误 - 无法计算XPath表达式:前缀必须解决一个命名空间:春

不过,我能得到它通过做以下工作(其中我认为可能是'正确的')。

下面是你的XML行,我改变:

<spring xmlns="" xmlns:spring="http://www.springframework.net"> 
    <spring:objects> 
     ... 
    </spring:objects> 

下面是修改后的XPath查询:

/spring/spring:objects/object[@id='CultureResolver']/@type 

为什么 '我的榜样' 和 '你的榜样' 是(巧妙地)错误

这个问题,我似乎(几乎没有)理解它,是声明一个名称空间没有前缀是非常不同的声明与前缀。

使用前缀声明名称空间只是声明名称空间及其前缀,但它不会更改任何元素的名称空间

声明不带前缀的名称空间使该名称空间成为其定义的元素以及该元素的所有子元素的默认名称空间。

所以,你的榜样,你可以修改下面一行在你的XML和你原来的XPath查询将工作:

<objects xmlns:spring="http://www.springframework.net"> 

[就在spring添加前缀命名空间。]

这因为(或者根据我的工作假设)将前缀添加到名称空间声明中,而不会将元素前缀添加到objects元素(及其所有子元素)中,因为会从名称空间中删除这些元素。

要正确添加前缀,而无需修改XML的语法,你的XML应该如下:

<spring> 
    <spring:objects xmlns:spring="http://www.springframework.net"> 
     <spring:object id="CultureResolver" type="Spring.Globalization.Resolvers.SessionCultureResolver, Spring.Web"> 
      <!--configure for server--> 
      <spring:property name="DefaultCulture" value="en" /> 
     </spring:object> 
    </spring:objects> 
</spring> 

而且你的XPath查询应该是这样的:

//spring/spring:objects/spring:object[@id='CultureResolver']/@type 

唯一的问题是,那不起作用(在the online tester,并且可能不与MSDeploy一起)。

上述不起作用,因为XPath引擎需要注册名称空间(与XML文档本身声明的名称空间分开)。但是,由于Web Deploy和在线测试人员似乎都这样做,XML文档的根元素中的任何声明都会自动注册。这非常有用,因为我不知道在使用Web Deploy参数转换时注册名称空间的方法。

有关更深入的解释,请参阅我的相关问题Do XML namespaces need to be declared in the root element to be matchable by an XPath query?的答案。

你(修正)例

XML:

<spring xmlns:spring="http://www.springframework.net"> 
    <spring:objects> 
     <spring:object id="CultureResolver" type="Spring.Globalization.Resolvers.SessionCultureResolver, Spring.Web"> 
      <!--configure for server--> 
      <spring:property name="DefaultCulture" value="en" /> 
     </spring:object> 
    </spring:objects> 
</spring> 

XPath查询:

//spring/spring:objects/spring:object[@id='CultureResolver']/@type 

结论

如果你不介意的长XPath查询,使用窍门在顶部。否则,请修改您的XML名称空间声明,以便它们包含前缀,并且它们位于XML文档的根元素中。

+2

你是一位绅士和学者,谢谢。在上线过程中,让我摆脱了困境。 – Michael12345 2017-05-27 07:15:18