Trying to replace XML element element using XDT and XPath locator

时光怂恿深爱的人放手 提交于 2020-01-11 06:23:52

问题


Hi I am trying to replace the <cron-expression> using VS2012 XDT by using the following transform on a quartz.net job description file. I have tested the XPath locator using an online tester and it returns 'what i think i need'. Any help is appreciated.

<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>

for the sample XML file (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>

The XPath //job-scheduling-data/schedule/trigger/cron[name='crontriggername2']

returns me the correct element group (http://www.freeformatter.com/xpath-tester.html1)

<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>

I based the expression on the solution to another XDT quesion on Log4net (log4Net config transform)

Can anybody point me to a correct solution, this is driving me insane. Thanks in advance.


回答1:


An alternative solution that does not need any modifications to the original file is

<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>

see also I am trying to get the Xpath for a value but getting error for nested condition




回答2:


Apply a namespace alias to the quartz namespace in the transform file (it can be left as the default in the original jobs config file) and use that alias on all the quartz nodes, including inside the XPath. Additionally you can use Condition rather than XPath and thus only specify the portion of the XPath expression that is relative to the current node's expression.

<?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>



回答3:


It's because your XML has a default namespace (http://quartznet.sourceforge.net/JobSchedulingData).

I don't know anything about XDT so I'm not sure of an easy way to declare the namespace but try googling for "xdt xpath default namespace".

In the mean time, here's a verbose option using local-name() that should work...

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



回答4:


Solution / Update is --> to add a namespace to the XML document and the XPath. All I needed to do was modify the XML and XPATH as follows.

First change the xml file adding a namespace (xmlns:ns0)

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

... then edit the file adding to all the nodes.

and finally the transform needs the namespace

<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>

For reference this link helped me understand

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




回答5:


Your transform XML needs to have the same default namespace (xmlns attribute) as the source XML. Also you shouldn't need the xdt:Locator attribute.

It should look like this:

   <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>


来源:https://stackoverflow.com/questions/22414628/trying-to-replace-xml-element-element-using-xdt-and-xpath-locator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!