Zan*_*ane 6 xml xpath msdeploy
我无法使用MSDeploy 更改Web.config中的元素.我的Parameters.xml文件:
<parameterEntry
kind="XmlFile"
scope="\\web.config$"
match="//spring/objects/object[@id='CultureResolver']/@type" />
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
你的例子有点棘手(起初).但是这个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
Run Code Online (Sandbox Code Playgroud)
我在回答 SO问题的过程中发现了这个技巧c# - 在XPath表达式中声明名称空间,但是在我已经发布了这个答案(最初)之后我才真正发现了它.
我在下面留下了我原来的大部分答案,并且还添加了关于我的原始答案是如何错误的额外部分.
我想为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>
Run Code Online (Sandbox Code Playgroud)
这是来自我的Parameters.xml文件的相关XPath查询,用于更改layout属性的parameter值为"roomId" 的元素的name属性:
/nlog/targets/target[@name='HipChat']/parameter[@name='roomId']/@layout
您可以使用此免费在线XPath测试程序确认上述XPath无法与所需属性匹配.您还可以使用Web Deploy本身确认它失败!
但是,无论是在线测试器还是通过Web Deploy,我都可以在不使用通配符或删除NLog.config中的命名空间声明的情况下使用它.诀窍是添加名称空间前缀.
以下是NLog.config中修改过的行:
<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>
Run Code Online (Sandbox Code Playgroud)
这是修改后的XPath查询:
/nlog:nlog/targets/target[@name='HipChat']/parameter[@name='roomId']/@layout
Run Code Online (Sandbox Code Playgroud)
我无法让你的例子在在线测试工作中只需添加一个前缀,你的例子使用的是命名空间(我没有使用Spring的项目).当我尝试添加前缀时测试仪的输出:
错误 - 无法评估XPath表达式:前缀必须解析为命名空间:spring
但是,通过执行以下操作,我能够让它工作(我认为可能是'正确的').
这是我改变的XML中的行:
<spring xmlns="" xmlns:spring="http://www.springframework.net">
<spring:objects>
...
</spring:objects>
Run Code Online (Sandbox Code Playgroud)
这是修改后的XPath查询:
/spring/spring:objects/object[@id='CultureResolver']/@type
Run Code Online (Sandbox Code Playgroud)
正如我似乎(几乎没有)理解的那样,问题是声明没有前缀的命名空间与声明带前缀的命名空间非常不同.
声明带前缀的命名空间只是声明命名空间及其前缀,但它不会更改任何元素的命名空间.
声明没有前缀的命名空间使该命名空间成为其定义的元素和该元素的所有子元素的默认命名空间.
因此,对于您的示例,您可以修改XML中的以下行,并且原始XPath查询将起作用:
<objects xmlns:spring="http://www.springframework.net">
Run Code Online (Sandbox Code Playgroud)
[只需spring在命名空间中添加前缀.]
这是因为(或根据我的工作假设)将前缀添加到名称空间声明中而不向objects元素(及其所有子项)添加前缀是"显着"修改XML,因为它正在从命名空间中删除这些元素.
要在不修改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>
Run Code Online (Sandbox Code Playgroud)
你的XPath查询应该是这样的:
//spring/spring:objects/spring:object[@id='CultureResolver']/@type
Run Code Online (Sandbox Code Playgroud)
唯一的问题是,这不起作用(在线测试器中,也可能不在MSDeploy中).
上述方法不起作用,因为XPath引擎需要注册名称空间(与XML文档本身声明的名称空间分开).但是,正如Web Deploy和在线测试人员所做的那样,XML文档的根元素中的任何声明都会自动注册.这非常有用,因为我不知道在使用Web Deploy参数转换时注册名称空间的任何方法.
有关更深入的解释,请参阅我的相关问题的答案.需要在根元素中声明XML命名空间是否可以通过XPath查询进行匹配?.
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>
Run Code Online (Sandbox Code Playgroud)
XPath查询:
//spring/spring:objects/spring:object[@id='CultureResolver']/@type
Run Code Online (Sandbox Code Playgroud)
如果您不介意长XPath查询,请使用顶部的技巧.否则,修改XML名称空间声明,使它们包含前缀,并且它们位于XML文档的根元素中.
问题是<objects/>元素上的名称空间声明.您的XPath查询没有匹配项,因为没有<objects/>带有空命名空间的元素(这是查询要查找的内容).
现在,在XPath中指定XML命名空间是一个棘手的问题(在这种情况下甚至是不可能的),所以我建议你使用这个表达式:
"//spring/*/*[@id='CultureResolver']/@type"
Run Code Online (Sandbox Code Playgroud)
HTH ...