Node.getTextContent() есть способ получить текстовое содержимое текущего node, а не текст потомка
Node.getTextContent() возвращает текстовое содержимое текущего node и его потомков.
есть способ получить текстовое содержимое текущего node, а не потокового текста.
Пример
<paragraph>
<link>XML</link>
is a
<strong>browser based XML editor</strong>
editor allows users to edit XML data in an intuitive word processor.
</paragraph>
ожидаемый выход
paragraph = is a editor allows users to edit XML data in an intuitive word processor.
link = XML
strong = browser based XML editor
Я попытался под кодом
String str = "<paragraph>"+
"<link>XML</link>"+
" is a "+
"<strong>browser based XML editor</strong>"+
"editor allows users to edit XML data in an intuitive word processor."+
"</paragraph>";
org.w3c.dom.Document domDoc = null;
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder;
try {
docBuilder = docFactory.newDocumentBuilder();
ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes());
domDoc = docBuilder.parse(bis);
} catch (ParserConfigurationException e1) {
e1.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
DocumentTraversal traversal = (DocumentTraversal) domDoc;
NodeIterator iterator = traversal.createNodeIterator(
domDoc.getDocumentElement(), NodeFilter.SHOW_ELEMENT, null, true);
for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) {
String tagname = ((Element) n).getTagName();
System.out.println(tagname + "=" + ((Element)n).getTextContent());
}
но он дает результат, подобный этому
paragraph=XML is a browser based XML editoreditor allows users to edit XML data in an intuitive word processor.
link=XML
strong=browser based XML editor
обратите внимание, что элемент paragraph содержит текст тега link и strong, который я не хочу.
предложите несколько идей?
Ответы
Ответ 1
Вы хотите отфильтровать дочерние элементы вашего node <paragraph>
, чтобы сохранить только node тип Node.TEXT_NODE
.
Это пример метода, который вернет вам желаемый контент
public static String getFirstLevelTextContent(Node node) {
NodeList list = node.getChildNodes();
StringBuilder textContent = new StringBuilder();
for (int i = 0; i < list.getLength(); ++i) {
Node child = list.item(i);
if (child.getNodeType() == Node.TEXT_NODE)
textContent.append(child.getTextContent());
}
return textContent.toString();
}
В вашем примере это означает:
String str = "<paragraph>" + //
"<link>XML</link>" + //
" is a " + //
"<strong>browser based XML editor</strong>" + //
"editor allows users to edit XML data in an intuitive word processor." + //
"</paragraph>";
Document domDoc = null;
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes());
domDoc = docBuilder.parse(bis);
} catch (Exception e) {
e.printStackTrace();
}
DocumentTraversal traversal = (DocumentTraversal) domDoc;
NodeIterator iterator = traversal.createNodeIterator(domDoc.getDocumentElement(), NodeFilter.SHOW_ELEMENT, null, true);
for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) {
String tagname = ((Element) n).getTagName();
System.out.println(tagname + "=" + getFirstLevelTextContent(n));
}
Вывод:
paragraph= is a editor allows users to edit XML data in an intuitive word processor.
link=XML
strong=browser based XML editor
Он выполняет итерацию по всем дочерним элементам Node, сохраняя только ТЕКСТ (исключая комментарии, node и т.д.) и накапливая их соответствующий текстовый контент.
В Node
или Element
нет прямого метода для получения только текстового содержимого на первом уровне.
Ответ 2
Если вы измените последний цикл for на следующий, он будет вести себя так, как вам хотелось.
for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) {
String tagname = ((Element) n).getTagName();
StringBuilder content = new StringBuilder();
NodeList children = n.getChildNodes();
for(int i=0; i<children.getLength(); i++) {
Node child = children.item(i);
if(child.getNodeName().equals("#text"))
content.append(child.getTextContent());
}
System.out.println(tagname + "=" + content);
}
Ответ 3
Я делаю это с потоками Java 8 и вспомогательным классом:
import java.util.*;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class NodeLists
{
/** converts a NodeList to java.util.List of Node */
static List<Node> list(NodeList nodeList)
{
List<Node> list = new ArrayList<>();
for(int i=0;i<nodeList.getLength();i++) {list.add(nodeList.item(i));}
return list;
}
}
И затем
NodeLists.list(node)
.filter(node->node.getNodeType()==Node.TEXT_NODE)
.map(Node::getTextContent)
.reduce("",(s,t)->s+t);
Ответ 4
Неявно нет никакой функции для фактического текста node, но с простым трюком вы можете это сделать. Спросите, есть ли node.getTextContent() содержит "\n", если это так, то фактический node не имеет никакого текста.
Надеюсь на эту помощь.