dom4j:在文本内容中添加PI

dom4j : adding PI in text content

我有以下元素:

<text>
text and text and text
<stop/>
text and text and text
<stop/>
text and text and text
<stop/>
</text>

而且我想在所有 'and' 文本之前和之后添加一条处理指令。像这样:

<text>
text<?Pub _newline>and<?Pub _newline>text<?Pub _newline>and<?Pub _newline>text
<stop/>
text<?Pub _newline>and<?Pub _newline>text<?Pub _newline>and<?Pub _newline>text
<stop/>
text<?Pub _newline>and<?Pub _newline>text<?Pub _newline>and<?Pub _newline>text
<stop/>
</text>

我不知道如何在文本中添加 PI 元素。如果我设置为字符串,它会被转义:&gt;?Pub _newline&lt;

示例文档中的 text 元素包含六个子节点:

  • 三个文本节点,每个节点包含文本text and text and text,以及
  • 三个元素(每个元素的名称都为stop)。

为了达到您想要的结果,我们需要将每个文本节点分解为文本节点和处理指令节点。

在dom4j中我们可以通过使用父元素的content来做到这一点。此方法 returns 元素所有子节点的列表,如果我们更改此列表,XML 文档也会更新。

因此,我们获取元素的内容列表,循环遍历所有子节点,当我们找到包含 and 的 Text 节点时,将该 Text 节点拆分为多个部分并将新部分插入到列表。

下面是演示此方法的方法。传递给它一个元素,它会按要求插入处理指令:

import org.dom4j.*;
import org.dom4j.tree.*;

// ...

public void insertProcessingInstructions(Element element) {
    List nodes = element.content();
    final String splitter = " and ";
    int index = 0;
    while (index < nodes.size()) {
        if (nodes.get(index) instanceof Text) {
            Text textNode = (Text)nodes.get(index);
            String text = textNode.getText();
            int andPos = text.indexOf(splitter);
            if (andPos >= 0) {
                String beforeText = text.substring(0, andPos);
                String afterText = text.substring(andPos + splitter.length());
                textNode.setText(beforeText);
                nodes.add(index + 1, new DefaultProcessingInstruction("Pub", "_newline"));
                nodes.add(index + 2, new DefaultText(splitter.trim()));
                nodes.add(index + 3, new DefaultProcessingInstruction("Pub", "_newline"));
                nodes.add(index + 4, new DefaultText(afterText));
                // Move to the last Text node created, in case it contains another
                // occurrence of the splitter string.
                index += 4; 
            } else {
                // No more occurrences of the splitter string in this Text node.
                ++index;
            }
        } else {
            // Not a Text node.
            ++index;
        }
    }
}