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文檔的根元素中。
非常感謝,對我也有效!對於那些使用Google搜索:與部署parameters.xml和Mvc.Sitemap相同的問題。由於mvcSiteMap節點中的xmlns,IIS導入無法像這樣匹配xpath:「/ mvcSiteMap/mvcSiteMapNode/mvcSiteMapNode [@ title ='My Title']/@ url」。 – Kirill 2014-09-26 12:42:54
您的解決方法絕對奏效,我在第一次找到您的答案時向您致敬,但最近我發現您錯了,無法正確編寫指定XML名稱空間的XPath查詢,並且以Web部署支持。 – 2015-01-24 19:15:46