Трюк с 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
Я обнаружил этот трюк в этот ответ на вопрос 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>
Вот соответствующий запрос XPath из моего Parameters.xml файла для изменения атрибута 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>
Вот модифицированный запрос XPath:
/nlog:nlog/targets/target[@name='HipChat']/parameter[@name='roomId']/@layout
Ваш пример
Я не смог заставить ваш пример работать в онлайн-тестере, просто добавив префикс, где ваш пример использует пространство имен (и у меня нет проекта, который использует Spring).Вывод тестера, когда я пытаюсь просто добавить префикс:
ОШИБКА - Не удалось оценить выражение XPath: префикс должен преобразовываться в пространство имен: spring
Однако,Я смог заставить его работать, выполнив следующее (что я думаю может быть «правильным»).
Вот строки в вашем 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, ваш 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
Единственная проблема в том, что это не работает (в онлайн-тестер , и, вероятно, также не с MSDeploy).
Вышеприведенное не работает, потому что движки XPath требуют регистрации пространств имен (отдельно от пространств имен, объявленных в самом документе XML).Но, как и веб-развертывание, и онлайн-тестер, любые объявления в корневом элементе 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>
Запрос XPath:
//spring/spring:objects/spring:object[@id='CultureResolver']/@type
Заключение
Если вы не возражаете против длинных запросов XPath,используйте трюк наверху.В противном случае измените декларации пространства имен XML таким образом, чтобы они включали префикс и располагались в корневом элементе вашего документа XML.