人们将有不同的方法来处理 XML 操作。这个问题的各种答案足以证明这一点。如果您想要一个良好且可维护的解决方案,则使用正则表达式和原始文本操作可能有利于一次性修复和黑客攻击,您应该使用 XML API。
我下面的示例执行了所要求的操作,但是应该注意的是,我没有检查任何异常输入,例如(""
作为搜索字符串)或处理 XML 命名空间。这些东西可以很容易地添加。
有关其工作原理的说明,请参见代码中的注释。
输入(test.xml):
<Callouts>
<Callout>Save the User Guide.</Callout>
</Callouts>
程序
package com.stackoverflow._18774666;
import java.net.URL;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
public class InsertElementInTextNode {
/**
* Replace text content of child text nodes of a parent element that
* matches a search string. The text is replace by an element named with the
* given name and has it's text content set equal to the search string.
*
* @param parent
* The element to search child text nodes of.
* @param elementName
* The name of the element to insert.
* @param text
* The text to replace with an element with same text content.
*/
public static void replaceTextWithElement(Element parent, String elementName, String text){
NodeList children = parent.getChildNodes();
Text cursor;
Element insertedElement;
int index;
/* Iterate children of the given element. */
for(int i = 0; i < children.getLength(); i++ ){
/* Check if this child is a text node. Ignore otherwise. */
if(children.item(i) instanceof Text){
cursor = (Text) children.item(i);
/* If the entire text node is equal to the search string,
* then we can replace it directly. Else we have split it.*/
if(text.equals(cursor.getData())){
/* Replace the text node with an element */
insertedElement = parent.getOwnerDocument().createElement(elementName);
insertedElement.setTextContent(text);
parent.replaceChild(insertedElement, cursor);
} else {
/* Check to see if the search string exists in this text node. Ignore otherwise.*/
index = cursor.getData().indexOf(text);
if(index != -1){
/* Replace the matched substring with an empty string.*/
cursor.replaceData(index, text.length(), "");
/* Create element to be inserted, and set the text content. */
insertedElement = parent.getOwnerDocument().createElement(elementName);
insertedElement.setTextContent(text);
/* Split the text node and insert the element in the middle. */
parent.insertBefore(insertedElement, cursor.splitText(index));
}
}
}
}
}
public static void main(String[] args) throws Exception {
/* Location of our XML document. */
URL xmlSource = InsertElementInTextNode.class.getResource("test.xml");
/* Parse with DOM in to a Document */
Document xmlDoc = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().parse(xmlSource.openStream());
/* Find our interesting elements. */
NodeList nodes = xmlDoc.getElementsByTagName("Callout");
/* Iterate through our interesting elements and check their content.*/
Element cursor;
for(int i = 0; i < nodes.getLength(); i++ ){
if(nodes.item(i) instanceof Element){
cursor = (Element) nodes.item(i);
replaceTextWithElement(cursor, "BookTitle", "User Guide");
}
}
/* Setup to output result. */
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
/* Printing result to stdout. */
transformer.transform(new DOMSource(xmlDoc),
new StreamResult(System.out));
}
}
输出(标准输出):
<Callouts>
<Callout>Save the <BookTitle>User Guide</BookTitle>.</Callout>
</Callouts>