Refactor only a portion of a file?

Oxygen general issues.
LaRae_Chasteen
Posts: 1
Joined: Tue Apr 09, 2019 9:14 pm

Refactor only a portion of a file?

Post by LaRae_Chasteen »

Good day,
Is there any way to perform one of the built-in refactoring operations, but only on selected text within the open file?
Thank you,
LaRae Chasteen
Radu
Posts: 9049
Joined: Fri Jul 09, 2004 5:18 pm

Re: Refactor only a portion of a file?

Post by Radu »

Dear LaRae,

Unfortunately the XML refactor can only be applied on entire documents, not on selected content. I added an internal issue with your feedback and if we ever implement this I will update the forum thread. In the meantime you will probably need to use the "Find/Replace" dialog which works on a selection. Or extract the selected content to a separate file and apply the refactoring operation there (but the selected content needs to be wellformed XML).

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Oleksii
Posts: 84
Joined: Wed Jul 19, 2017 6:04 pm
Location: Austria
Contact:

Re: Refactor only a portion of a file?

Post by Oleksii »

Are there any news on this topic in the meantime? This kind of feature would be extremely useful.
It would be nice to be able to customize something like currently available Surround with tags which you can invoke with a shortcut.
Kind regards,
Oleksii Sapov-Erlinger
Radu
Posts: 9049
Joined: Fri Jul 09, 2004 5:18 pm

Re: Refactor only a portion of a file?

Post by Radu »

Hi Oleksii,

If you are working with the XML doc in the Author visual editing mode, you can create custom Author operation based on our predefined XSLT and XQuery operations:

https://www.oxygenxml.com/doc/versions/ ... yoperation

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Oleksii
Posts: 84
Joined: Wed Jul 19, 2017 6:04 pm
Location: Austria
Contact:

Re: Refactor only a portion of a file?

Post by Oleksii »

Hi Radu,

yes, I know about this possibility in Author mode and it would be an alternative. The point is that we are working with XML in MEI (https://dme.mozarteum.at/movi/navigator/525/001/01) namespace. Currently, we do not have an appropriate CSS for displaying it which could be also a bit tricky because an MEI document structure consists mainly of elements and their attributes. So we are working in the text mode only.

Regards,
Oleksii
Kind regards,
Oleksii Sapov-Erlinger
Radu
Posts: 9049
Joined: Fri Jul 09, 2004 5:18 pm

Re: Refactor only a portion of a file?

Post by Radu »

Hi Oleksii,

I understand, the only work around right now is to create an Oxygen plugin which adds some contextual menu actions in the Text editing mode which obtain the selected content, process it using XSLT and then replace the selection with the processed content.
We have lots of API, you can implement Oxygen plugins even using Javascript:

https://github.com/oxygenxml/wsaccess-j ... onTextPage

If you have someone willing to work on this I can guide them.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Oleksii
Posts: 84
Joined: Wed Jul 19, 2017 6:04 pm
Location: Austria
Contact:

Re: Refactor only a portion of a file?

Post by Oleksii »

Hi Radu,

thank you, I'll take a closer look then.
As an even shorter workaround could be also to use a code template (options >> templates >> code templates) with ${selection} but especially if it could be evaluated through
${xpath_eval()}.
I tried to do

Code: Select all

${xpath_eval(
 ${selection}//* 
)}
or

Code: Select all

${xpath_eval(
let $n := ${selection}
return $n
)}
just to access the selection but obviously it is not serialized as an element. I also searched for XPath functions to convert string to a node-set or document node but didn't find anything. Maybe if you look behind the scenes of the ${selection} and ${xpath_eval()} you'll have an idea?

Regards,
Oleksii
Kind regards,
Oleksii Sapov-Erlinger
Radu
Posts: 9049
Joined: Fri Jul 09, 2004 5:18 pm

Re: Refactor only a portion of a file?

Post by Radu »

Hi Oleksii,

If you want to go down that path of using xpath_eval, there is a Saxon function called parse-xml, it's used something like:

Code: Select all

${xpath_eval(parse-xml('${selection}')//*)}
but from my tests it seems the serialized output contains some extra namespaces, I managed to remove them with something like:

Code: Select all

${xpath_eval(
replace(
'${xpath_eval(parse-xml('${selection}')//*)}', 
' xmlns:xml="http://www.w3.org/XML/1998/namespace"', 
'')
)}
I will add an internal issue to see why those xmlns:xml namespace mappings get serialized.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Oleksii
Posts: 84
Joined: Wed Jul 19, 2017 6:04 pm
Location: Austria
Contact:

Re: Refactor only a portion of a file?

Post by Oleksii »

Hi Radu,

I solved my particular problem for now as I needed the following value:

Code: Select all

${xpath_eval(
	(parse-xml('${selection}')//*[@xml:id])[1]/@xml:id/substring-after(., '_')
)}
But the example with replace() didn't work for me. I played around, also checking maybe the problem is something with a sequence handling but it didn't work either as I'm getting an empty sequence as a result of the evaluation:

Code: Select all

${xpath_eval(
		for $n in
			parse-xml('${selection}')//*
		return
			replace($n, ' xmlns:xml="http://www.w3.org/XML/1998/namespace"', 
		'' )
)}
Just replace() works, however:

Code: Select all

${xpath_eval(
	replace('abc', 'a', '')
)}
here is an xml snippet:

Code: Select all

<mei meiversion="3.0.0" xmlns="http://www.music-encoding.org/ns/mei">
	<staff dme.parts="11" n="7" xml:id="staff_18930">
		<layer n="1" xml:id="layer_18936">
			<mRest tstamp="1" xml:id="mRest_18942"/>
		</layer>
	</staff>
</mei>
The result is :

Code: Select all

<mei meiversion="3.0.0" xmlns="http://www.music-encoding.org/ns/mei">
	
		
			
		
	
			
		
</mei>
Kind regards,
Oleksii Sapov-Erlinger
Radu
Posts: 9049
Joined: Fri Jul 09, 2004 5:18 pm

Re: Refactor only a portion of a file?

Post by Radu »

Hi Oleksii,

Running replace on a node like you do:

Code: Select all

replace($n, ' xmlns:xml="http://www.w3.org/XML/1998/namespace"
is most probably invalid, you can run the replace on plain strings but once you have called the parse-xml, you have nodes there and not serialized XML strings.

This is why in the approach I gave you I first run the xpath evaluation to obtain the node set and the return of the method serializes the node set to an XML string, then I use an outer xpath evaluation which uses replace to replace in that returned string the xml prefix mapping which should not be there in the first place. So maybe you can take a look again at my example which uses the xpath_eval twice, an xpath eval which replaces and the inner xpath eval which actually does the processing.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Oleksii
Posts: 84
Joined: Wed Jul 19, 2017 6:04 pm
Location: Austria
Contact:

Re: Refactor only a portion of a file?

Post by Oleksii »

Hi Radu,

the first thing I did was copy+paste of your code examples. :) As it didn't work for me (still getting empty string) I tried to play around.
I also noticed that you use xpath_eval() twice. It is strange it doesn't work for me.
oXygen 20.1

Regards,
Oleksii
Kind regards,
Oleksii Sapov-Erlinger
Radu
Posts: 9049
Joined: Fri Jul 09, 2004 5:18 pm

Re: Refactor only a portion of a file?

Post by Radu »

Hi Oleksii,

In Oxygen 21.1 we made a major change in how our editor variables are evaluated, resulting in more flexibility when it comes to computing such constructs. So I was using in my tests Oxygen 21.1.

Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
sorin_carbunaru
Posts: 402
Joined: Mon May 09, 2016 9:37 am

Re: Refactor only a portion of a file?

Post by sorin_carbunaru »

Hello,

Just wanted to let everybody know that the generation of extra "xmlns:xml" namespaces was fixed in the recently released oXygen 22.

Best wishes,
Sorin Carbunaru
oXygen XML
Oleksii
Posts: 84
Joined: Wed Jul 19, 2017 6:04 pm
Location: Austria
Contact:

Embedding $ask{} into a code template.

Post by Oleksii »

Hi,
The code template should add an attribute to multiple selected nodes at once, and it works fine like this:

Code: Select all

${xpath_eval(
let $node := parse-xml-fragment('${selection}')/node(),
$string := serialize($node),
$pattern := '(<.*?)(/>)',
$replacement := '$1 stem.dir="down" $2',
$output :=    replace($string, $pattern, $replacement)
  return    
$output
  )}	
Applying to the descendants of <beam>:

Code: Select all

    <beam xml:id="beam_17514">
                      <note artic="spicc" dur="8" oct="3" pname="a" tstamp="1.5" xml:id="note_17520"/>
                      <note artic="spicc" dur="8" oct="4" pname="c" tstamp="2" xml:id="note_17526"/>
                      <note accid="s" artic="spicc" dur="8" oct="3" pname="f" tstamp="2.5" xml:id="note_17532"/>
         </beam>
I get this:

Code: Select all

<beam xml:id="beam_17514">
                      <note artic="spicc" doxml.id="d27e3443" dur="8" oct="3" pname="a" tstamp="1.5" xml:id="note_17520" stem.dir="up" />
                      <note artic="spicc" doxml.id="d27e3445" dur="8" oct="4" pname="c" tstamp="2" xml:id="note_17526" stem.dir="up" />
                      <note accid="s" artic="spicc" doxml.id="d27e3447" dur="8" oct="3" pname="f" tstamp="2.5" xml:id="note_17532" stem.dir="up" />
                    </beam>
But the value of @stem.dir could be different, so it would be useful when the user can define the value dynamically. I wanted to implement this:

Code: Select all

${xpath_eval(
let $node := parse-xml-fragment('${selection}')/node(),
$string := serialize($node),
$pattern := '(<.*?)(/>)',
$attributeVal := "${ask('@stem.dir=', editable_combobox,('up':'up';'down':'down'), 'up')}",
$replacement := concat('$1 ', 'stem.dir="', $attributeVal, '" $2'),
$output := replace($string, $pattern, $replacement)
  return    
$output
  )}	
But it replaces the nodes with empty space, which usually happens when something fails. Through trial & error I found out that it could be something with fn:replace(). Because when using fn:concat() instead the combobox opens and the code works as expected:

Code: Select all

${xpath_eval(
let $node := parse-xml-fragment('${selection}')/node(),
$string := serialize($node),
$pattern := '(<.*?)(/>)',
$attributeVal := "${ask('@stem.dir=', editable_combobox,('up':'up';'down':'down'), 'up')}",
$replacement := concat('$1 ', 'stem.dir="', $attributeVal, '" $2'),
$output := concat($string, $pattern, $replacement)
  return    
$output
  )}	
Kind regards,
Oleksii Sapov-Erlinger
alex_jitianu
Posts: 1008
Joined: Wed Nov 16, 2005 11:11 am

Re: Refactor only a portion of a file?

Post by alex_jitianu »

Hello,

I've tested with an Oxygen 23.1 build and the code template worked as expected. The dialog appears, I give a value and @stem.dir is set to that value. What version of Oxygen are you running? Perhaps this was an issue that we fixed at some point.

Best regards,
Alex
Oleksii
Posts: 84
Joined: Wed Jul 19, 2017 6:04 pm
Location: Austria
Contact:

Re: Refactor only a portion of a file?

Post by Oleksii »

I'm using 20.1, build 2020010914
Kind regards,
Oleksii Sapov-Erlinger
alex_jitianu
Posts: 1008
Joined: Wed Nov 16, 2005 11:11 am

Re: Refactor only a portion of a file?

Post by alex_jitianu »

Hi,

I'm sorry, but in version 20 we had a primitive editor expansion engine, which didn't treat all the nesting possibilities. We introduce a new engine in Oxygen 21.1.

Best regards,
Alex
Post Reply