Page 1 of 1

Schema aware content inseration with required content

Posted: Fri Nov 01, 2013 3:52 pm
by SSC
Hello,

I do use the
ro.sync.ecss.extensions.api.AuthorDocumentController.insertXMLFragmentSchemaAware(String, int) to insert certain xml elements with DITA conrefs.

When I insert a conref of an <ul>, I do call something similar like that:

Code: Select all


ro.sync.ecss.extensions.api.AuthorDocumentController.insertXMLFragmentSchemaAware("<ul conref=\"#topicId/elementId\"/>", desiredOffset)
The conref is shown correctly here, but the dtd shows errors, because the <ul> XML element is incomplete(because of the missing <li> child element), even though it is just a conref and the <li> child would not be shown anyway.

Is there an easy way available for me to insert the <ul> and other really "SchemaAware"(like the method is already named), so that a <li> element is automatically generated in this case?

Best regards,

Simon

Re: Schema aware content inseration with required content

Posted: Fri Nov 01, 2013 4:36 pm
by Radu
Hi Simon,

The schema aware insertion API you are using does not auto-fill the XML fragment. It just checks if the fragment can be inserted at the caret location and if not it proposes the user a couple of strategies in order to insert the fragment in a proper location in the document.

But you have enough API to create a fragment (AuthorDocumentFragment object) which contains all required content elements. Here's an example with DITA:

Code: Select all

 AuthorSchemaManager schemaManager = this.authorAccess.getDocumentController().getAuthorSchemaManager();
WhatElementsCanGoHereContext context = schemaManager.createWhatElementsCanGoHereContext(this.authorAccess.getEditorAccess().getCaretOffset());
List<CIElement> possibleElementsAtCaretPosition = schemaManager.whatElementsCanGoHere(context);
loop: for (int i = 0; i < possibleElementsAtCaretPosition.size(); i++) {
CIElement possibleElement = possibleElementsAtCaretPosition.get(i);
List<CIAttribute> attrs = possibleElement.getAttributes();
if(attrs != null) {
for (int j = 0; j < attrs.size(); j++) {
CIAttribute ciAttribute = attrs.get(j);
if (ciAttribute.getName().equals("class")) {
if (ciAttribute.getDefaultValue() != null
&& ciAttribute.getDefaultValue().contains(" topic/ul ")) {
//Found a CIElement for ul
//Create a fragment for it. The fragment contains all required child elements already built.
AuthorDocumentFragment frag = schemaManager.createAuthorDocumentFragment(possibleElement);
//Now set the @conref to it.
List<AuthorNode> nodes = frag.getContentNodes();
if(!nodes.isEmpty()) {
AuthorElement imageEl = (AuthorElement) nodes.get(0);
imageEl.setAttribute("conref", new AttrValue("#topicId/elementId"));
}
//You can then use the API to insert this fragment at the caret position.
break loop;
}
}
}
}
}
Regards,
Radu

Re: Schema aware content inseration with required content

Posted: Mon Nov 04, 2013 1:18 pm
by SSC
Hello Radu,

I do use the ro.sync.ecss.extensions.api.AuthorDocumentController.insertXMLFragmentSchemaAware("<CertainElementWithConrefAttribute", desiredOffset), because of the nice Dialog, which comes up if the new content is not inserted at a correct offset according to the schema and then offers alternative inseration places.

What I actually want is a complete(schema-valid) ro.sync.ecss.extensions.api.node.AuthorDocumentFragment, which I can pass to the ro.sync.ecss.extensions.api.AuthorDocumentController.insertFragmentSchemaAware(int, AuthorDocumentFragment) method, which offers the nice Dialog with alternative insertation options according to the schema.

I´d already tried that:

Code: Select all


        AuthorDocumentFragment fragmentInContext = authorAccess
.getDocumentController().createNewDocumentFragmentInContext(
sb.toString(), offset);

authorAccess.getDocumentController().insertFragmentSchemaAware(offset,
fragmentInContext);
But the ro.sync.ecss.extensions.api.AuthorDocumentController.createNewDocumentFragmentInContext(String, int) also does not generate a schema aware AuthorDocumentFragment

So I guess only the ro.sync.ecss.extensions.api.AuthorSchemaManager.createAuthorDocumentFragment(CIElement) method generates such a valid AuthorDocumentFragment, right?

But how do I get the desired CIElement from a String, which just contains the name of the XML element?

Best regards,

Simon

Re: Schema aware content inseration with required content

Posted: Mon Nov 04, 2013 1:43 pm
by SSC
Hi Radu,

or is it somehow possible to get only the required elements of an existing element, so that I can add those elements afterwards? After the node with the schema aware dialog is used?

Best regards,

Simon

Re: Schema aware content inseration with required content

Posted: Mon Nov 04, 2013 4:58 pm
by Radu
Hi Simon,
So I guess only the ro.sync.ecss.extensions.api.AuthorSchemaManager.createAuthorDocumentFragment(CIElement) method generates such a valid AuthorDocumentFragment, right?
Yes, you need to use the schema manager if you want to create a fragment which has all required elements and attributes filled in.
But how do I get the desired CIElement from a String, which just contains the name of the XML element?
Please look at the sample code I posted.
The code I posted has at some point:

You can then use the API to insert this fragment at the caret position.

So it creates an AuthorDocumentFragment object which can either be inserted directly or converted to XML using AuthorDocumentController.serializeFragmentToXML(AuthorDocumentFragment)
or is it somehow possible to get only the required elements of an existing element, so that I can add those elements afterwards? After the node with the schema aware dialog is used?
Yes, you can also do this.
First use the API to create a context:
AuthorSchemaManager.createWhatElementsCanGoHereContext(int)

then you use this API to get a list of allowed elements at the caret position:

AuthorSchemaManager.getChildrenElements(WhatElementsCanGoHereContext)

A CIElement object has a method called CIElement.getGuessElements() which returns the list of required child elements in it.
But it is easier to let Oxygen create the fragment for you as shown in my sample code.

Regards,
Radu

Re: Schema aware content inseration with required content

Posted: Wed Nov 06, 2013 6:04 pm
by SSC
Hello Radu,

the problem about your solution is that I just get the ro.sync.contentcompletion.xml.WhatElementsCanGoHereContext for the caret position.
But in case the caret position is not valid for the element, which is supposed to be inserted, and the dialog with alternatives appears, the caret position will be a different one, if the user chooses a different position in the dialog.

Your solution only works for the use case, when the user drops an xml string like <ul conref="id"/> at a valid position in the xml content, because then the returned ro.sync.contentcompletion.xml.WhatElementsCanGoHereContext will also contain the <ul> ro.sync.contentcompletion.xml.CIElement, which can be used to generate a valid <ul> xml element at the caret position.

But if the user drops a xml string, which looks like <ul conref="id"/> at a invalid location, I won´t get a WhatElementsCanGoHereContext with an <ul> xml element in it.
Because of that I want to try inserting the <ul> with the authorAccess.getDocumentController().insertFragmentSchemaAware(offset,fragmentInContext); so that the dialog is shown to the user and the user is able to chose a different location.
But after the user has chosen a different location the <ul> xml element is directly inserted and does not contain the required childelements and attributes.

So I need to access the <ul> xml element and append the required childelements after the "dialog" has inserted the dropped <ul> xml element at a valid location.

I hope that you now got what I want to achieve?

When the <ul> xml element is inserted at an alternative location by the dialog, the caret is placed inside the new <ul> element. Can I something receive a CIElement of the <ul> xml element in order to know which "GuessElements" has to be appended?

By the way the "<ul> xml element" is just an example. It should work for any XML element, which will be dropped onto the editor.

Best regards,

Simon

Re: Schema aware content inseration with required content

Posted: Wed Nov 06, 2013 6:20 pm
by Radu
Hi Simon,

I understand, you can use this API:

Code: Select all

ro.sync.ecss.extensions.api.AuthorSchemaManager.getGlobalElements()
to get a list of all global elements, find the CIElement corresponding to the "<ul>", create the fragment from it using:

Code: Select all

ro.sync.ecss.extensions.api.AuthorSchemaManager.createAuthorDocumentFragment(CIElement)
set the attribute on the fragment, or serialize the fragment to XML, set the attribute on it and then insert it using the schema aware actions.

Regards,
Radu