Попытка заменить элемент элемента XML с помощью XDT и локатора XPath

Привет я пытаюсь заменить <cron-expression> использование VS2012 XDT с помощью следующего преобразования в файле описания задания quartz.net. Я протестировал локатор XPath с помощью онлайн-тестера, и он возвращает "то, что мне нужно". Любая помощь приветствуется.

<schedule>
    <trigger>
        <cron xdt:Locator="XPath(//job-scheduling-data/schedule/trigger/cron[name='crontriggername2'])" >
            <cron-expression  xdt:Transform="Replace">***some data***</cron-expression>
        </cron>
    </trigger>
</schedule>

для образца XML-файла (Quartz.net)

  <job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"><processing-directives>
    <overwrite-existing-data>true</overwrite-existing-data>
</processing-directives>

<schedule>
       <trigger>
        <cron>
            <name>crontriggername1</name>
            <group>crontriggergroup1</group>
            <description>crontriggerdesc1</description>
            <job-name>crontriggerjobname1</job-name>
            <job-group>crontriggerjgroup1</job-group>
            <misfire-instruction>crontriggermisfile1</misfire-instruction>
            <cron-expression>0/5 * * * * ?</cron-expression>
        </cron>
    </trigger>

    <trigger>
        <cron>
            <name>crontriggername2</name>
            <group>crontriggergroup2</group>
            <description>crontriggerdesc2</description>
            <job-name>crontriggerjobname2</job-name>
            <job-group>crontriggerjgroup2</job-group>
            <misfire-instruction>crontriggermisfile2</misfire-instruction>
            <cron-expression>0/13 * * * * ?</cron-expression>
        </cron>
    </trigger>      
</schedule>

XPath // данные-задания-расписания / расписания / триггера /cron[name='crontriggername2']

возвращает мне правильную группу элементов ( http://www.freeformatter.com/xpath-tester.html 1)

<cron>
  <name>crontriggername2</name>
  <group>crontriggergroup2</group>
  <description>crontriggerdesc2</description>
  <job-name>crontriggerjobname2</job-name>
  <job-group>crontriggerjgroup2</job-group>
  <misfire-instruction>crontriggermisfile2</misfire-instruction>
  <cron-expression>0/13 * * * * ?</cron-expression>
</cron>

Я основал выражение на решении другого вопроса XDT в Log4net ( преобразование конфигурации log4Net)

Кто-нибудь может указать мне на правильное решение, это сводит меня с ума. Заранее спасибо.

5 ответов

Решение

Альтернативное решение, которое не требует каких-либо изменений в исходном файле:

<job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<schedule>
    <trigger>


        <cron xdt:Locator="XPath(//*[local-name()='job-scheduling-data']
                                 /*[local-name()='schedule']
                                 /*[local-name()='trigger']
                                 /*[local-name()='cron']
                                   [*[local-name() = 'name'] = 'MyTriggerName'])">

or this syntax...

        <cron xdt:Locator="XPath(//*[local-name()='job-scheduling-data' and namespace-uri()='http://quartznet.sourceforge.net/JobSchedulingData']
                                 /*[local-name()='schedule' and namespace-uri()='http://quartznet.sourceforge.net/JobSchedulingData']
                                 /*[local-name()='trigger' and namespace-uri()='http://quartznet.sourceforge.net/JobSchedulingData']
                                 /*[local-name()='cron' and namespace-uri()='http://quartznet.sourceforge.net/JobSchedulingData']
                                   [*[local-name() = 'name'] = 'MyTriggerName'])">

            <cron-expression  xdt:Transform="Replace">***some data***</cron-expression>
        </cron>
    </trigger>
</schedule>

см. также я пытаюсь получить Xpath для значения, но получаю ошибку для вложенного условия

Примените псевдоним пространства имен к кварцевому пространству имен в файле преобразования (его можно оставить по умолчанию в файле конфигурации исходных заданий) и используйте этот псевдоним на всех кварцевых узлах, в том числе внутри XPath. Дополнительно вы можете использовать Condition скорее, чем XPath и, таким образом, указывается только часть выражения XPath, относящаяся к выражению текущего узла.

<?xml version="1.0" encoding="utf-8" ?>
<q:job-scheduling-data xmlns:q="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <q:schedule>
        <q:trigger>
            <q:cron xdt:Locator="Condition(q:name='crontriggername2')" >
                <q:cron-expression xdt:Transform="Replace">***some data***</q:cron-expression>
            </q:cron>
        </q:trigger>
    </q:schedule>
</q:job-scheduling-data>

Решение / Обновление -> добавить пространство имен к документу XML и XPath. Все, что мне нужно было сделать, это изменить XML и XPATH следующим образом.

Сначала измените файл XML, добавив пространство имен (xmlns: ns0)

<job-scheduling-data xmlns:ns0="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0">

... затем отредактируйте файл, добавив его ко всем узлам.

и, наконец, преобразование нуждается в пространстве имен

<job-scheduling-data xmlns:ns0="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <schedule>
        <trigger>
            <cron xdt:Locator="XPath(//job-scheduling-data/schedule/trigger/cron[name='crontriggername2'])" >
                <cron-expression  xdt:Transform="Replace">***some data***</cron-expression>
            </cron>
        </trigger>
</schedule>

Для справки эта ссылка помогла мне понять

http://hypnocode.azurewebsites.net/?p=36

Это потому, что ваш XML имеет пространство имен по умолчанию (http://quartznet.sourceforge.net/JobSchedulingData).

Я ничего не знаю о XDT, поэтому я не уверен в простом способе объявить пространство имен, но попробуйте поискать "xdt xpath default namespace".

В то же время, вот подробный вариант с использованием local-name() это должно работать...

XPath(//*[local-name()='job-scheduling-data']/*[local-name()='schedule']/*[local-name()='trigger']/*[local-name()='cron' and *[local-name()='name']='crontriggername2'])

XML-преобразование должно иметь то же пространство имен по умолчанию (xmlns атрибут) в качестве исходного XML. Также вам не нужен атрибут xdt:Locator.

Это должно выглядеть так:

   <job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
      <schedule>
          <trigger>
              <cron>
                  <cron-expression  xdt:Transform="Replace">***some data***</cron-expression>
              </cron>
          </trigger>
      </schedule>
   </job-scheduling-data>
Другие вопросы по тегам