JAVA, NodeList XML 在不知道te XML 内容的情况下得到所有children
JAVA, NodeList XML get all the children without knowing the content of te XML
我正在使用 Vaadin,一个 Java 框架。
我使用 XML 内容,我想用这些信息制作一棵树,但我不知道 XML 内容会持续多久。我发送了一个呼叫以获取 XML,但使用了不同的 IP 地址。
我知道如何获得 child,以及下一个 child。但我想自动化这个功能,比如,检查 XML 有多长,然后循环直到结束。
这里是我的代码:
private void getData(NodeSet data)
{
InputStream dataXml = new ByteArrayInputStream(data.toXMLString().getBytes(StandardCharsets.UTF_8));
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try
{
final DocumentBuilder builder = factory.newDocumentBuilder();
final Document document = builder.parse(dataXml);
final Element racine = document.getDocumentElement();
final NodeList racineNoeuds = racine.getChildNodes();
final int nbRacineNoeuds = racineNoeuds.getLength();
for (int i = 0; i < nbRacineNoeuds; i++)
{
//System.out.print(nbRacineNoeuds);
//System.out.print(racineNoeuds);
if (racineNoeuds.item(i).getNodeType() == Node.ELEMENT_NODE)
{
final Element child = (Element) racineNoeuds.item(i);
final NodeList racineChild = child.getChildNodes();
final int nbRacineChild = racineChild.getLength();
for (int y = 0; y < nbRacineChild; y++)
{
if (racineChild.item(y).getNodeType() == Node.ELEMENT_NODE)
{
final Element child2 = (Element) racineChild.item(y);
final NodeList children = child2.getChildNodes();
final int nbChildren = children.getLength();
for (int a = 0; a < nbChildren; a++)
{
if (children.item(a).getNodeType() == Node.ELEMENT_NODE)
{
final Element child3 = (Element) children.item(y);
}
}
}
}
//System.out.print(child);
//tree.setParent(racineChild, child);
}
/*tree.addItem(racine);
tree.addItem(racineNoeuds);
tree.setParent(racineNoeuds, racine);
tree.addItem(child);
tree.setParent(child, racine);
tree.addItem(child2);
tree.setParent(child2, child);
tree.addItem(child3);
tree.setParent(child3, child2);*/
}
} catch (final ParserConfigurationException e)
{
e.printStackTrace();
} catch (final SAXException e)
{
e.printStackTrace();
} catch (final IOException e)
{
e.printStackTrace();
}
}
谢谢!
由于我的回答来得比较晚,我想这主要是为了后代:)
确实,正如@Morfic 所指出的,递归方法可能是您现在可以实现的最简单的方法来完成任务。
我创建了一个tiny project to illustrate a very basic solution. It contains a DataSource
class providing some test data and a main Vaadin UI,其内容是一个Tree
,由您需要的递归方法填充.
/**
* If <code>parentId</code> is <code>null</code> then the <code>element</code>'s
* name or value gets added directly under <code>tree</code>.
*/
private void loadTree(Tree tree, Object parentId, Node element) {
if (tree == null || element == null) {
return;
}
// 1. We add to the tree what's given to us as argument:
final String itemId =
(element.getNodeType() == Node.TEXT_NODE ? element.getNodeValue() : element.getNodeName()).trim();
if (itemId.length() == 0) {
return; // skip eventual white spaces...
}
tree.addItem(itemId); // a tree item's label defaults to its ID
// 2. If a parent ID is also provided as argument, we set that as parent for the newly added item
if (parentId != null) {
tree.setParent(itemId, parentId);
}
// 3. We then _recursively_ add to the tree every child of the given element (if any):
NodeList children = element.getChildNodes();
for (int i = 0, n = children.getLength(); i < n; i++) {
loadTree(tree, itemId, children.item(i));
}
// 4. Optionally we can expand an item if it has any children or force hiding the arrow if not:
if (children.getLength() > 0) {
tree.expandItem(itemId);
} else {
tree.setChildrenAllowed(itemId, false);
}
}
该方法首先向提供的 Tree
添加一个项目,其标签/ID 是根据 Node
的内容或名称创建的。如果还给出了父 ID,我们将其设置为新添加节点的父 ID。然后,如果给定的 Node
有任何子项,我们递归地为每个子项调用该方法,提供新创建项的 ID 作为父项。
这应该可以解决问题。话虽如此,有些事情你应该(重新)考虑:
虽然简单,但如果 XML(非常)大,递归实现可能会给您带来麻烦;然后您可能会选择相同方法的迭代实现(通常不是很难获得,一旦提供了递归方法)
显然,在第一次调用时,parentId
参数可以/应该保留 null
。由于这会使代码更难理解(通常 null
参数不是很清楚),您可以使用 private void loadTree(Tree tree, Node element) { loadTree(tree, null, element); }
重载方法,在其中隐藏丑陋的参数;只是更方便来电...
我显然直接在UI中使用了XMLDOM模型/API——通常不是最好的主意(即将应用程序的 UI 与低级模型相结合);在更复杂的应用程序中,我们确实有更好的模型(域模型、UI 模型等);同样,人们可能喜欢使用 HierarchicalContainer
Tree
组件(目前)在 Vaadin 8 中没有对应的组件;因此,该项目仅适用于(不包括)8
版本的 Vaadin
Bon course alors ;)
我正在使用 Vaadin,一个 Java 框架。
我使用 XML 内容,我想用这些信息制作一棵树,但我不知道 XML 内容会持续多久。我发送了一个呼叫以获取 XML,但使用了不同的 IP 地址。
我知道如何获得 child,以及下一个 child。但我想自动化这个功能,比如,检查 XML 有多长,然后循环直到结束。
这里是我的代码:
private void getData(NodeSet data)
{
InputStream dataXml = new ByteArrayInputStream(data.toXMLString().getBytes(StandardCharsets.UTF_8));
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try
{
final DocumentBuilder builder = factory.newDocumentBuilder();
final Document document = builder.parse(dataXml);
final Element racine = document.getDocumentElement();
final NodeList racineNoeuds = racine.getChildNodes();
final int nbRacineNoeuds = racineNoeuds.getLength();
for (int i = 0; i < nbRacineNoeuds; i++)
{
//System.out.print(nbRacineNoeuds);
//System.out.print(racineNoeuds);
if (racineNoeuds.item(i).getNodeType() == Node.ELEMENT_NODE)
{
final Element child = (Element) racineNoeuds.item(i);
final NodeList racineChild = child.getChildNodes();
final int nbRacineChild = racineChild.getLength();
for (int y = 0; y < nbRacineChild; y++)
{
if (racineChild.item(y).getNodeType() == Node.ELEMENT_NODE)
{
final Element child2 = (Element) racineChild.item(y);
final NodeList children = child2.getChildNodes();
final int nbChildren = children.getLength();
for (int a = 0; a < nbChildren; a++)
{
if (children.item(a).getNodeType() == Node.ELEMENT_NODE)
{
final Element child3 = (Element) children.item(y);
}
}
}
}
//System.out.print(child);
//tree.setParent(racineChild, child);
}
/*tree.addItem(racine);
tree.addItem(racineNoeuds);
tree.setParent(racineNoeuds, racine);
tree.addItem(child);
tree.setParent(child, racine);
tree.addItem(child2);
tree.setParent(child2, child);
tree.addItem(child3);
tree.setParent(child3, child2);*/
}
} catch (final ParserConfigurationException e)
{
e.printStackTrace();
} catch (final SAXException e)
{
e.printStackTrace();
} catch (final IOException e)
{
e.printStackTrace();
}
}
谢谢!
由于我的回答来得比较晚,我想这主要是为了后代:)
确实,正如@Morfic 所指出的,递归方法可能是您现在可以实现的最简单的方法来完成任务。
我创建了一个tiny project to illustrate a very basic solution. It contains a DataSource
class providing some test data and a main Vaadin UI,其内容是一个Tree
,由您需要的递归方法填充.
/**
* If <code>parentId</code> is <code>null</code> then the <code>element</code>'s
* name or value gets added directly under <code>tree</code>.
*/
private void loadTree(Tree tree, Object parentId, Node element) {
if (tree == null || element == null) {
return;
}
// 1. We add to the tree what's given to us as argument:
final String itemId =
(element.getNodeType() == Node.TEXT_NODE ? element.getNodeValue() : element.getNodeName()).trim();
if (itemId.length() == 0) {
return; // skip eventual white spaces...
}
tree.addItem(itemId); // a tree item's label defaults to its ID
// 2. If a parent ID is also provided as argument, we set that as parent for the newly added item
if (parentId != null) {
tree.setParent(itemId, parentId);
}
// 3. We then _recursively_ add to the tree every child of the given element (if any):
NodeList children = element.getChildNodes();
for (int i = 0, n = children.getLength(); i < n; i++) {
loadTree(tree, itemId, children.item(i));
}
// 4. Optionally we can expand an item if it has any children or force hiding the arrow if not:
if (children.getLength() > 0) {
tree.expandItem(itemId);
} else {
tree.setChildrenAllowed(itemId, false);
}
}
该方法首先向提供的 Tree
添加一个项目,其标签/ID 是根据 Node
的内容或名称创建的。如果还给出了父 ID,我们将其设置为新添加节点的父 ID。然后,如果给定的 Node
有任何子项,我们递归地为每个子项调用该方法,提供新创建项的 ID 作为父项。
这应该可以解决问题。话虽如此,有些事情你应该(重新)考虑:
虽然简单,但如果 XML(非常)大,递归实现可能会给您带来麻烦;然后您可能会选择相同方法的迭代实现(通常不是很难获得,一旦提供了递归方法)
显然,在第一次调用时,
parentId
参数可以/应该保留null
。由于这会使代码更难理解(通常null
参数不是很清楚),您可以使用private void loadTree(Tree tree, Node element) { loadTree(tree, null, element); }
重载方法,在其中隐藏丑陋的参数;只是更方便来电...我显然直接在UI中使用了XMLDOM模型/API——通常不是最好的主意(即将应用程序的 UI 与低级模型相结合);在更复杂的应用程序中,我们确实有更好的模型(域模型、UI 模型等);同样,人们可能喜欢使用 HierarchicalContainer
Tree
组件(目前)在 Vaadin 8 中没有对应的组件;因此,该项目仅适用于(不包括)8 版本的 Vaadin
Bon course alors ;)