Find/Replace in Files

Post here questions and problems related to oXygen frameworks/document types.
Gerardo
Posts: 8
Joined: Thu Jun 17, 2021 11:58 pm

Find/Replace in Files

Post by Gerardo » Tue Jun 29, 2021 8:31 pm

Hi,

Is there an API to use "Find/Replace in Files" feature from a plug-in? We want to modify some values in our dita files and we are wondering if we can wrap the existing functionality in a plugin and make the UI simpler to writers.

Thanks
Gerardo
Attachments
image.png
image.png (42.22 KiB) Viewed 496 times

Radu
Posts: 7594
Joined: Fri Jul 09, 2004 5:18 pm

Re: Find/Replace in Files

Post by Radu » Wed Jun 30, 2021 7:18 am

Hi Gerardo,

I'm afraid not but we do have the possibility to add custom XML refactoring based on XSLT stylesheets operations to Oxygen:
https://www.oxygenxml.com/doc/versions/ ... tools.html

An Oxygen plugin can contribute a folder of XML refactoring operations:
https://www.oxygenxml.com/doc/versions/ ... nsion.html

and later, when you right click in Oxygen's Project folder there is a "Refactoring->XML Refactoring" action allowing you to choose a refactoring action to apply on the selected files.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com

Gerardo
Posts: 8
Joined: Thu Jun 17, 2021 11:58 pm

Re: Find/Replace in Files

Post by Gerardo » Wed Jul 07, 2021 7:26 pm

Hi Radu,

I have read all the documentation about the refactoring tool and even made some simple custom operations. In general it fulfills our needs.

Is it possible to show in the Configure Operation Parameters Wizard Page a list with possible values fetched by a REST API service? I see it is possible to hard-code them in the Custom Refactoring Operation Descriptor File but that might not provide us with the flexibility we need.

The user scenario that we want to accomplish is to update in multiple files the person who owns those file. The owner ID is store in a author node.

<author type="owner">gchava</author>

The text node in the author node cannot be an open text field due to the risk of typos. There should be only well-formed IDs which is not something that Oxygen can know by itself, so ideally the Refactoring Tool should show a list of valid IDs fetched by another system who know what the valid IDs are.

I hope I was clear

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<!--
    Descriptor for the 'Replace element with XML fragment' operation. 
-->
<refactoringOperationDescriptor 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.oxygenxml.com/ns/xmlRefactoring" 
    id="update-owner-metadata" 
    name="Update Owner Metada">
  <description>Updates owner metadata</description>    
  <script type="XQUERY_UPDATE" href="update-owner-metadata.xq"/>
  <category>Metadata</category>
    <parameters>
      <description>Enter a valid name and value</description>
	  <parameter name="curr_owner" label="Current Owner" type="TEXT">
        <description>Current owner</description>
		<possibleValues onlyPossibleValuesAllowed="true">
		  <value name="gsilva">gsilva</value>
		  <value name="gchava">gchava</value>
        </possibleValues>
      </parameter> 
      <parameter name="new_owner" label="New Owner" type="TEXT">
        <description>New owner that will replace the current owner with</description>
        <possibleValues onlyPossibleValuesAllowed="true">
                  <!--
                 This list must be a dynamic list fetched by a REST Service
                  -->
		  <value name="gsilva">gsilva</value>
		  <value name="gchava">gchava</value>
        </possibleValues>
      </parameter>    	    
    </parameters>
</refactoringOperationDescriptor>

Code: Select all

xquery version "3.0" encoding "utf-8";

(: 
    XQuery document used to implement 'Replace element with XML fragment' operation.    
:)

import module namespace xr = "http://www.oxygenxml.com/ns/xmlRefactoring" at "http://www.oxygenxml.com/ns/xmlRefactoring/resources/commons.xq";

declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";

declare option output:method   "xml";
declare option output:indent   "no";

declare variable $curr_owner as xs:string external; 
declare variable $element_xpath := concat("//author[@type='owner' and data()='", $curr_owner, "']");


(: The XML fragment to be inserted :)
declare variable $new_owner as xs:string external; 

(: Parse the XML fragment :)
let $xmlFragmentSequence as node()* := xr:parse-xml-fragment(concat("<author type='owner'>", $new_owner, "</author>"))
let $elements := saxon:evaluate($element_xpath)
for $elem in $elements
where $elem instance of element()
return 
  (
    (: Insert the nodes from the XML fragment before the target element :)
    insert nodes $xmlFragmentSequence before $elem,
         
    (: Delete the target element :)     
    delete node $elem
  )   

Radu
Posts: 7594
Joined: Fri Jul 09, 2004 5:18 pm

Re: Find/Replace in Files

Post by Radu » Thu Jul 08, 2021 7:20 am

Hi Gerardo,

Right now the values for a parameter can only be taken from the XML descriptor file. We have an internal issue to allow for example calling a small XSLT script for computing values for certain parameter types in the XML descriptor file.
Coming back to your use case, maybe you can create an XSLT stylesheet which generates the XML descriptor file by taking into account values returned by the Rest API. And use that XSLT from time to time to re-generate the XML descriptor file when new authors are added to the system.
Or at least if you leave the parameter value as a simple field perform a validation of the value in the XSLT by calling the rest api and checking the value in the field matches a value on the server...

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com

Gerardo
Posts: 8
Joined: Thu Jun 17, 2021 11:58 pm

Re: Find/Replace in Files

Post by Gerardo » Fri Jul 09, 2021 7:48 am

Hi Radu,

Validating the input against the server sounds like a good alternative. Do you have a sample project or something where I can see how to call a rest api from the XSLT?

Thanks

Radu
Posts: 7594
Joined: Fri Jul 09, 2004 5:18 pm

Re: Find/Replace in Files

Post by Radu » Fri Jul 09, 2021 7:58 am

Hi,

The XSLT document() function can be called to load XML content from some http URL:
https://www.saxonica.com/html/documenta ... ument.html

There is also the XSLT 3.0 unparsed-text function which can be called to return as text the contents of an URL:
https://www.saxonica.com/html/documenta ... -text.html

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com

Gerardo
Posts: 8
Joined: Thu Jun 17, 2021 11:58 pm

Re: Find/Replace in Files

Post by Gerardo » Tue Jul 13, 2021 2:35 am

Hi Radu,

I have modified my script and now I am validating the entered ID against a list of valid IDs. If the new owner is valid, I replace the author node´s value with the entered ID. Otherwise I just ignore the operation.

Code: Select all

xquery version "3.0" encoding "utf-8";

(: 
    XQuery document used to implement 'Replace element with XML fragment' operation.    
:)

import module namespace xr = "http://www.oxygenxml.com/ns/xmlRefactoring" at "http://www.oxygenxml.com/ns/xmlRefactoring/resources/commons.xq";

declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";

declare option output:method   "xml";
declare option output:indent   "no";

declare variable $curr_owner as xs:string external; 
declare variable $element_xpath := concat("//author[@type='owner' and data()='", $curr_owner, "']");

(: The XML fragment to be inserted :)
declare variable $new_owner as xs:string external; 

(: Valid IDs :)
for $str in ("gchava", "gsilva")
where $str = $new_owner
return (

  (: Parse the XML fragment :)
  let $xmlFragmentSequence as node()* := xr:parse-xml-fragment(concat("<author type='owner'>", $new_owner, "</author>"))
  let $elements := saxon:evaluate($element_xpath)

  for $elem in $elements
  where $elem instance of element()
  return 
  (
     (: Insert the nodes from the XML fragment before the target element :)
     insert nodes $xmlFragmentSequence before $elem,
         
     (: Delete the target element :)     
     delete node $elem
  )
 
)
For clarity purposes, I would also like to show an alert indicating the reason why the operation didn't succeed. So, how can I show a pop dialog alerting writers about the error?

Thanks in advance
Gerardo

Radu
Posts: 7594
Joined: Fri Jul 09, 2004 5:18 pm

Re: Find/Replace in Files

Post by Radu » Thu Jul 15, 2021 6:51 am

Hi Gerardo,

XQuery does not have API to show an error message, it can however use the fn:error function to break processing and Oxygen should present the problem in the problems list:
http://www.xqueryfunctions.com/xq/fn_error.html

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com

Post Reply