odftoolkit icon indicating copy to clipboard operation
odftoolkit copied to clipboard

having trouble with inserting context at index

Open AnharMiah opened this issue 5 years ago • 5 comments

hello all, I'm not entirely sure if this is the correct repo to be asking this, but the documentation/resources/websites are so very confusing!

Anyway I've been banging my head against the wall on this problem for a day now and can't seem to get it to work!

Any pointers or help would be highly appreciated!

Some context:

We have an ODF text document (this can be considered as a template), and it has a bunch of text added such as <FOO_LIST>.

What we're trying to then do is simply find all instances of the above and then programmatically inserting a bullet point list at that text location.

Simple in theory right?

Well what I have almost works, however instead of placing the bullet point list near those "place holders" they just get added to the start of the document :(

anyway here is the gist of the code (its in Kotlin):

fun BulletPoints(data: List<String>, mount: String, doc: TextDocument) {
        try {
            val search = TextNavigation("<$mount>", doc)

            while (search.hasNext()) {
                val item: TextSelection = search.nextSelection() as TextSelection
                val p = doc.getParagraphByIndex(item.index, false)

                val tempDoc = TextDocument.newTextDocument()
                tempDoc.addList().addItems(data.toTypedArray())

                doc.insertContentFromDocumentAfter(tempDoc, p, false)
            }
        } catch (e: Exception) {
            throw Exception
        }
    }

AnharMiah avatar Mar 11 '20 16:03 AnharMiah

Hello Anhar Hussain Miah,

Am Mi., 11. März 2020 um 17:48 Uhr schrieb Anhar Hussain Miah < [email protected]>:

hello all, I'm not entirely sure is this is the correct repo to be asking this, but the documentation/resources/websites are so very confusing!

Oh, that might be true. I have a task to finish this, but get constantly distracted by paid work :-) Do you have some suggestions to improve this situation?

Anyway I've been banging my head against the wall on this problem for a day now and can't seem to get it to work!

Any pointers or help would be highly appreciated!

Some context:

We have an ODF text document (this can be considered as a template), and it has a bunch of text added such as <FOO_LIST>.

What we're trying to then do is simply find all instances of the above and then programmatically inserting a bullet point list at that text location.

Simple in theory right?

Not really, what do you like to get as a return from the search? Most likely you will receive a string from the content of the paragraph/heading containing your "triggering character sequence" (pattern)? This String object is likely a copy of the text of the paragraph (concatenated from all the span etc. elements) and no longer attached to the DOM tree of the document you like to manipulate.

If you want to do an XML mutation on your document based on a patter you might want to do the following:

  1. You might want to traverse the DOM instance of the document to find your pattern (as an example, for recursion take a look at the OdfElement.toString() method). In your case, you need to find the text node (or even better of the paragraph/heading) containing the text pattern.
  2. You might provide the desired document XML mutation as a function as an argument that takes the paragraph/heading as an input or a bit more sophisticated in case you work with ODFDOM 1.0.0_SNAPSHOT branch you can describe your mutation as a list of changes: https://tdf.github.io/odftoolkit/docs/odfdom/operations/operations.html You might provide a list of JSON changes - similar to a batch program - that is applied to the document.

From what I heard, you might need to split the paragraph, insert a list, etc.

Would be a nice example for future documentation. :-)

Well what I have almost works, however instead of placing the bullet point list near those "place holders" they just get added to the start of the document :(

anyway here is the gist of the code (its in Kotlin):

fun BulletPoints(data: List<String>, mount: String, doc: TextDocument) { try { val search = TextNavigation("<$mount>", doc)

        while (search.hasNext()) {
            val item: TextSelection = search.nextSelection() as TextSelection
            val p = doc.getParagraphByIndex(item.index, false)

            val tempDoc = TextDocument.newTextDocument()
            tempDoc.addList().addItems(data.toTypedArray())

            doc.insertContentFromDocumentAfter(tempDoc, p, false)
        }
    } catch (e: Exception) {
        throw Exception
    }
}

I am unfortunately missing the context, but I assume you are still using the Simple API, which is deprecated. You should work with the ODFDOM module on the 1.0.0_SNAPSHOT branch.

Sorry for the docu confusion, I will try to fix it in a not so distant future ;-) Svante

You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/tdf/odftoolkit/issues/31, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAGJNW3IK7SRTR2AIKTOAUDRG66HLANCNFSM4LF2ESEQ .

svanteschubert avatar Mar 11 '20 17:03 svanteschubert

hi @svanteschubert thanks for the feedback! I highly appreciate it!

I'll have a look at ODFDOM module, do you think its possible to essentially insert things like bullet points, tables etc at certain predefined place holders throughout the document?

Any further pointers would be super appreciated!

AnharMiah avatar Mar 11 '20 18:03 AnharMiah

Hello Anhar Hussain Miah,

of course, you might do anything you like on a DOM tree similar to HTML DOM. The existing operations are just a subset of what is possible but help you with nasty details and might be too complex for your use case.

BTW I have forgotten one example source you might want to reuse if you do not rely on the operations directly, but programming functionality for yourself. The ODFDOM is using a typed DOM tree. Instead of solely Element and Attribute classes we have our own classes for each XML node like for table:table element we have the TableTableElement class. Each is derived from the OdfElement class and there you will find a lot of very useful tooling methods, such as

  • markText(int textPosStart, int textPosEnd, JSONObject formatChanges)
  • split(int posStart)
  • replaceChild(Node newChild, Node oldChild)

I suggest you search as well for their usage to find examples and take a look at the tests beyond odfdom/src/test/java/org/odftoolkit/odfdom/

Good luck! Svante

Am Mi., 11. März 2020 um 19:07 Uhr schrieb Anhar Hussain Miah < [email protected]>:

hi @svanteschubert https://github.com/svanteschubert thanks for the feedback! I highly appreciate it!

I'll have a look at ODFDOM module, do you think its possible to essentially insert the things like bullet points, tables etc at certain predefined place holders throughout the document?

Any further pointers would be super appreciated!

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/tdf/odftoolkit/issues/31#issuecomment-597785517, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAGJNW6MTDBYEZF3BMBZ3FLRG7HOPANCNFSM4LF2ESEQ .

svanteschubert avatar Mar 11 '20 18:03 svanteschubert

Oliver Rau suggested you use org.odftoolkit.odfdom.incubator.search.TextStyleNavigation you create it with a pattern and receive a TextSelection, where you can call getElement() to receive the DOM node.

This is not our code, but I will enhance it to use JDK Iterator & Iterable interfaces. Oliver did it this way: final TextNavigation search = new TextNavigation(FIELD_PATTERN, inputDocument); while (search.hasNext()) { // search for the next selection final TextSelection item = (TextSelection) search.nextSelection();

Looking at the code of TextStyleNavigation hasNext seems to search for the next item and is not idempotent:

@Override public boolean hasNext() { mCurrentSelectedItem = findnext(mCurrentSelectedItem); return (mCurrentSelectedItem != null); }

Let me fix this all on the 1.0.0_SNAPSHOT branch soon, but you may already start working.. ;-)

svanteschubert avatar Mar 12 '20 13:03 svanteschubert

thanks @svanteschubert I really appreciate your time on this!

I've solved this specific case in a different way today:

In the original document, I simply placed a single bullet point list like:

  • <FOO>

then I iterated over all lists in that document looking for an item that matched <FOO>, once it matched I simply appended the list items and removed the first entry!

AnharMiah avatar Mar 12 '20 13:03 AnharMiah