Finding the node at the caret positoin
Post here questions and problems related to oXygen frameworks/document types.
Finding the node at the caret positoin
Hi,
In a plugin I need to extract data from at document relative to the current node, i.e. the node at which the caret is. First I need to find that node. I am using evaluateXPath(). The problem is crafting the Xpath expression that will yield the correct node. I have found that the . operator will select the current element. If the caret is in a text node the . operator will select the enclosing element node. node() and text() will sometimes select way to much for my need. I will illustrate with this very simplified example:
If I place the caret at "textinside" both node() and text() will select the current text node and nothing else. If however I place the caret at "textoutside" evaluateXPath() will return an array of nodes and I do not know how to pick the one with the caret in. node() will select everything inside "bigelement", both element nodes and text nodes. text() will select the four text nodes that are inside "bigelement" but not inside "element":
My question is: Can I craft an XPath expression that will return the text node with the caret in this case? If not, can I find (using Java code) which of the returned text nodes contain the caret?
In a plugin I need to extract data from at document relative to the current node, i.e. the node at which the caret is. First I need to find that node. I am using evaluateXPath(). The problem is crafting the Xpath expression that will yield the correct node. I have found that the . operator will select the current element. If the caret is in a text node the . operator will select the enclosing element node. node() and text() will sometimes select way to much for my need. I will illustrate with this very simplified example:
Code: Select all
<xml>
<bigelement>
<element> textinside </element> textoutside
<element> textinside </element> textoutside
<element> textinside </element> textoutside
</bigelement>
<bigelement>
<element> textinside </element> textoutside
<element> textinside </element> textoutside with caret
<element> textinside </element> textoutside
</bigelement>
</xml>
Code: Select all
/xml[1]/bigelement[2]/text()[1]
textoutside /xml[1]/bigelement[2]/text()[2]
textoutside with caret /xml[1]/bigelement[2]/text()[3]
textoutside /xml[1]/bigelement[2]/text()[4]
Re: Finding the node at the caret positoin
Hi,
Unfortunately for the text page we do not have much API to help you navigate the nodes structure, we'll try to add more API for a future version.
My only suggestion would be something like this (I did not test the code below but with some small changes it should work):
Regards,
Radu
Unfortunately for the text page we do not have much API to help you navigate the nodes structure, we'll try to add more API for a future version.
My only suggestion would be something like this (I did not test the code below but with some small changes it should work):
Code: Select all
WSXMLTextNodeRange[] elementsByXPath = xmlTextPage.findElementsByXPath(".");
if(elementsByXPath != null && elementsByXPath.length > 0){
//This should always be only one match, the entire XML element inside which the caret is placed.
WSXMLTextNodeRange range = elementsByXPath[0];
int startOffset = xmlTextPage.getOffsetOfLineStart(range.getStartLine()) + range.getStartColumn() - 1;
int endOffsetOffset = xmlTextPage.getOffsetOfLineStart(range.getEndLine()) + range.getEndColumn() - 1;
int caretOffset = xmlTextPage.getCaretOffset();
//This should be a string containing all the XML element content (including start and end tags).
String xmlText = xmlTextPage.getDocument().getText(startOffset, endOffsetOffset - startOffset);
int offsetInXMLTextRelativeToStartRange = caretOffset - startOffset;
int lastEndTagOffset = xmlText.substring(0, offsetInXMLTextRelativeToStartRange).lastIndexOf(">");
int firstStartTagOffset = xmlText.indexOf("<", offsetInXMLTextRelativeToStartRange);
if(firstStartTagOffset != -1 && lastEndTagOffset != -1 && firstStartTagOffset < lastEndTagOffset){
//The text node containing the caret should be between them
String textNodeContent = xmlText.substring(lastEndTagOffset + 1, firstStartTagOffset);
}
}
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
<oXygen/> XML Editor
http://www.oxygenxml.com
Re: Finding the node at the caret positoin
Thank you for the reply. I see that I will have to create some kind of workaround rather than believe I can craft a super XPath. That is actually helpful to know.
In the real application I am actually looking for data that is relative to the node with the caret. For example something like this:
A possible workaround could be to use getCaretOffset() to compare to the output from findElementsByXPath() to select which of the outputs from evaluateXPath()to use. This assumes the two functions returnes the same number and sequence of nodes.
Another workaround might be to use regexp rather than XPath.
Thanks for your help!
Re possible future API I may have two immediate suggestions:
1) Implement current() and let it represent the exact node at the caret (whatever node type that is). This will not break compatibility since current() is not currently implemented. The difference between what is returned from the . operator and current() may break peoples expectations.
2) Create an Oxygen proprietary function that returns the number of the caret containing node of a sequence. This would allow a construct like:
In the real application I am actually looking for data that is relative to the node with the caret. For example something like this:
Code: Select all
(node()/preceding::*/@href)[last()]
Another workaround might be to use regexp rather than XPath.
Thanks for your help!
Re possible future API I may have two immediate suggestions:
1) Implement current() and let it represent the exact node at the caret (whatever node type that is). This will not break compatibility since current() is not currently implemented. The difference between what is returned from the . operator and current() may break peoples expectations.
2) Create an Oxygen proprietary function that returns the number of the caret containing node of a sequence. This would allow a construct like:
Code: Select all
node()[oxy_caretposition()]
Re: Finding the node at the caret positoin
Hi,
Please see some comments below:
to get all the direct child text nodes of the current element in which the caret is, then use the text ranges to search for the range where the caret is placed. This could possibly work and be more elegant than my proposed workaround.
Regards,
Radu
Please see some comments below:
Right, so call for example:A possible workaround could be to use getCaretOffset() to compare to the output from findElementsByXPath() to select which of the outputs from evaluateXPath()to use. This assumes the two functions returnes the same number and sequence of nodes.
Code: Select all
WSXMLTextNodeRange[] ranges = access.findElementsByXPath("text()");
Yes, regexp is a possible fallback, using XML aware ways is always better if possible.Another workaround might be to use regexp rather than XPath.
We'll take this into account, thanks for giving us feedback.Re possible future API I may have two immediate suggestions:
1) Implement current() and let it represent the exact node at the caret (whatever node type that is). This will not break compatibility since current() is not currently implemented. The difference between what is returned from the . operator and current() may break peoples expectations.
2) Create an Oxygen proprietary function that returns the number of the caret containing node of a sequence. This would allow a construct like:
Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
<oXygen/> XML Editor
http://www.oxygenxml.com
Re: Finding the node at the caret positoin
Hi Barbara,
So you are interested in API for the Text editing mode, right?
I did not find any mention that the proposals were implemented. But there is this method:
https://www.oxygenxml.com/InstData/Edit ... oller.html
which allows you to insert XML fragments relative to a certain XPath expression which could be "." for example.
Regards,
Radu
So you are interested in API for the Text editing mode, right?
I did not find any mention that the proposals were implemented. But there is this method:
Code: Select all
ro.sync.exml.workspace.api.editor.page.text.xml.WSXMLTextEditorPage.getDocumentController()
which allows you to insert XML fragments relative to a certain XPath expression which could be "." for example.
Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
<oXygen/> XML Editor
http://www.oxygenxml.com
Return to “SDK-API, Frameworks - Document Types”
Jump to
- Oxygen XML Editor/Author/Developer
- ↳ Feature Request
- ↳ Common Problems
- ↳ DITA (Editing and Publishing DITA Content)
- ↳ SDK-API, Frameworks - Document Types
- ↳ DocBook
- ↳ TEI
- ↳ XHTML
- ↳ Other Issues
- Oxygen XML Web Author
- ↳ Feature Request
- ↳ Common Problems
- Oxygen Content Fusion
- ↳ Feature Request
- ↳ Common Problems
- Oxygen JSON Editor
- ↳ Feature Request
- ↳ Common Problems
- Oxygen PDF Chemistry
- ↳ Feature Request
- ↳ Common Problems
- Oxygen Feedback
- ↳ Feature Request
- ↳ Common Problems
- Oxygen XML WebHelp
- ↳ Feature Request
- ↳ Common Problems
- XML
- ↳ General XML Questions
- ↳ XSLT and FOP
- ↳ XML Schemas
- ↳ XQuery
- NVDL
- ↳ General NVDL Issues
- ↳ oNVDL Related Issues
- XML Services Market
- ↳ Offer a Service