MakeParagraphsCmd
converts text lines contained in the clipboard to a sequence of paragraphs. This is a simplified version of command formatTextAs
in XMLmind XML Editor - Commands.
MakeParagraphsCmd
shows you how to avoid writing a validating command.
Authors often need to paste in their XML documents text blocks copied from a word processor.
Without a special command, doing so is tedious because:
The author must create a blank paragraph in the XML document.
The author must paste text copied from the clipboard inside this paragraph.
If multiple text blocks have been copied, the author must remove open lines and split the paragraph in multiple pieces.
A special command can do all this automatically. Such a command is a validating one because the author must not be allowed to insert captured paragraphs in places which would make the document invalid.
The paste
command in XMLmind XML Editor - Commands can be passed plain text or an XML string (a string which starts with "<?xml
") as its parameter. So why not use this standard validating command to do the paragraph insertion?
The idea here is to write a simple command, MakeParagraphsCmd
, which returns an XML string containing one or several paragraphs built using clipboard content. This string is then passed to the paste
command which inserts the paragraphs (if the XML Schema or the DTD constraining the document allows to do so).
Note that MakeParagraphsCmd
cannot be used alone. It must be part of a macro-command such as the following one (DocBook example):
<command name="insertAfterAsSimpara"> <macro> <sequence> <command name="MakeParagraphsCmd" parameter="simpara" /> <command name="paste" parameter="after[implicitElement] %_" /> </sequence> </macro> </command>
Excerpts from MakeParagraphsCmd.java
:
public class MakeParagraphsCmd extends CommandBase { private Name elementName; private boolean blocks; private String pastable; public MakeParagraphsCmd() { super(/*repeatable*/ false, /*recordable*/ true); } public boolean prepare(DocumentView docView, String parameter, int x, int y) { elementName = null; blocks = false; pastable = null; if (docView.getDocument() == null) { return false; } if (parameter == null || parameter.length() == 0) { return false; } String name = null; int pos = parameter.lastIndexOf(']'); if (pos < 0) { name = parameter; } else if (pos+1 < parameter.length()) { name = parameter.substring(pos+1); } if (name != null) { elementName = Name.fromString(name.trim()); } if (elementName == null) { return false; } blocks = (parameter.indexOf("[blocks]") >= 0); pastable = docView.getXMLClipboard().get(); if (pastable == null || pastable.length() == 0 || pastable.startsWith("<?xml ")) { return false; } return true; } ...
This command must be passed a parameter. | |
After option
| |
If the | |
The clipboard contents must be accessed using | |
|
public CommandResult doExecute(DocumentView docView, String parameter, int x, int y) { ArrayList<String> textList = new ArrayList<String>(); StringBuilder block = new StringBuilder(); LineNumberReader lines = new LineNumberReader(new StringReader(pastable)); String line; while ((line = readLine(lines)) != null) { line = XMLText.collapseWhiteSpace(line); if (line.length() == 0) { // Open line. if (blocks && block.length() > 0) { textList.add(block.toString()); block = new StringBuilder(); } continue; } line = XMLText.filterText(line); if (blocks) { if (block.length() > 0) { block.append(' '); } block.append(line); } else { textList.add(line); } } if (blocks && block.length() > 0) { textList.add(block.toString()); } int count = textList.size(); if (count == 0) { return CommandResult.FAILED; } // The content of the clipboard is fetched as a *Java String*. // Therefore no need to specify encoding in the XML declaration. StringBuilder result = new StringBuilder(); result.append("<?xml version='1.0'?>"); openTag(ClipboardFormat.ENVELOPE_NAME, result); for (int i = 0; i < count; ++i) { String text = (String) textList.get(i); openTag(elementName, result); XMLText.escapeXML(text, result); closeTag(elementName, result); } closeTag(ClipboardFormat.ENVELOPE_NAME, result); return CommandResult.done(result.toString()); }
This loop reads the content of the clipboard line by line and, for each paragraph that needs to be created, adds its textual content to | |
Whitespace contained in the textual content of a future paragraph is collapsed using utility | |
Non-XML characters contained in the textual content of a future paragraph are discarded using utility | |
The content of the clipboard is fetched as a string. Therefore there is no need to specify an encoding in the XML declaration. | |
XXE only supports text inside the clipboard. This text is considered to be XML (that is, not plain text) if it starts with " As expected, the following text is parsed as a single <?xml version="1.0"?><p>Paragraph #1.</p> Using special wrapper element <?xml version="1.0"?> <ns:clipboard xmlns:ns="http://www.xmlmind.com/xmleditor/namespace/clipboard"> <p>Paragraph #1.</p> <p>Paragraph #2.</p> </ns:clipboard> |