Как изменить элемент XML в пространстве имен с помощью файла MSDeploy Parameters.xml? - PullRequest
6 голосов
/ 29 апреля 2011

Я не могу изменить элемент в Web.config с MSDeploy. Мой Parameters.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>

Ответы [ 2 ]

8 голосов
/ 23 января 2015

Трюк с 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.

7 голосов
/ 06 мая 2011

проблема в объявлении пространства имен для элемента <objects/>. Ваш запрос XPath не имеет соответствия, потому что нет элемента <objects/> с пустым пространством имен (это то, что ищет запрос).

Теперь, указание пространств имен XML в XPath является сложной задачей (в данном случае это даже невозможно), поэтому я бы предложил использовать вместо этого выражение:

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

НТН ...

...