Java。移入与 child 具有相同标签名称的 xml
Java. Moving in a xml with the same tag name as child
我遇到的问题是我必须使用我工作的公司的提供商发送给我的 xml 文件。
如果 xml 构造良好但根本不是问题。
<catalog>
<product>
<ref>4780</ref>
.
.
.
<arrivals>
<product>
<image title="AMARILLO">AMA</image>
<size>S/T </size>
</product>
<product>
<image title="AZUL">AZUL</image>
<size>S/T </size>
</product>
</arrivals>
</product>
</catalog>
如您所见,标签<product>
包含了产品的所有信息,但还有更多名为<product>
的标签,以便在颜色不同时进行区分。
这是我用来在 xml.
中移动的代码
doc = db.parse("filename.xml");
Element esproducte = (Element)doc.getElementsByTagName("product").item(0);
NodeList nArrv = esproducte.getElementsByTagName("arrivals");
Element eArrv = (Element) nArrv.item(0);
NodeList eProds = eArrv.getElementsByTagName("product");//THIS THING
for(int l=0; l<eProds.getLength(); l++)
{
Node ln = eProds.item(l);
if (ln.getNodeType() == Node.ELEMENT_NODE)
{
Element le = (Element) ln;
//COLORS / IMAGES / CONFIGS
NodeList nimgcol = le.getElementsByTagName("image");
Element eimgcol = (Element) nimgcol.item(0);
System.out.println("Name of the color " + eimgcol.getTextContent());
}
实际情况是打印重复了更多次,我认为这是因为父 <product>
。我认为这不应该发生,因为我在写 //THIS THING
的地方考虑到了 <product>
设置在 <arrivals>
中的事实。但它不起作用。
我应该在代码中修改什么以在 for 中仅移动 2 次而不是 3 次,这是在这种情况下发生的情况?
解法:
NodeList eProds = eArrv.getElementsByTagName("product");//THIS THING
到
NodeList eProds = eArrv.getChildNodes();//THIS THING
其他的完全一样。完美运行。
完全 有效 在不同的父元素中添加标签,这些元素的名称相同,但具有不同的 content/meaning,就像您的示例中的情况一样。
路径为 /catalog/product
的元素与路径为 /catalog/product/arrivals/product
的元素完全不同。例如,XPath 和 XML Schema 将认为它们是不同的。
只是懒惰写的代码无法区分差异,例如通过使用 getElementsByTagName
,它将元素定位到任何位置 ("all descendants") 而不管位置(路径)。
处理 DOM 树时,以结构化方式进行:
- 迭代根 (
catalog
) 的所有子元素(不是所有后代)。
- 根据严格性,如果元素未命名则失败
product
.
- 对于名为
product
的每个元素:
- 迭代
product
元素的所有子元素。
- 按名称处理元素,例如
ref
, arrivals
.
- 如果严格,如果元素名称未知则失败。
- 如果元素名称是
arrivals
:
- 迭代
arrivals
元素的所有子元素。
- 如果严格,如果元素未命名则失败
product
.
- 对于名为
product
的每个元素:
- 按名称处理元素,例如
image
, size
.
- 如果严格,如果元素名称未知则失败。
如您所见,代码中在名为 catalog
的元素内处理名为 product
的元素的位置与在名为 product
的元素内处理名为 product
的元素的代码不同名为 arrivals
.
的元素
getElementsByTagName
为您提供该标签内名称为 "product" 的所有标签,包括颜色的 "product" 标签。
尝试使用 getChildNodes
并改为检查节点的名称
正如 Andreas 所提到的,文档没有任何无效之处,问题在于使用 getElementsByTagName,它只是扫描整个文档以查找具有该标签名称的任何元素,而不管结构如何。
您可以使用 XPath 来简化特定元素的遍历。
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.*;
import java.io.IOException;
import java.io.StringReader;
public class XMLParsing {
public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException, XPathExpressionException {
String xml = "<catalog>\n" +
" <product>\n" +
" <ref>4780</ref>\n" +
" .\n" +
" .\n" +
" .\n" +
" <arrivals>\n" +
" <product>\n" +
" <image title=\"AMARILLO\">AMA</image>\n" +
" <size>S/T </size>\n" +
" </product>\n" +
" <product>\n" +
" <image title=\"AZUL\">AZUL</image>\n" +
" <size>S/T </size>\n" +
" </product>\n" +
" </arrivals>\n" +
" </product>\n" +
"</catalog>\n";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new InputSource(new StringReader(xml)));
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
// get all products under "arrivals"
XPathExpression expression = xPath.compile("/catalog/product/arrivals//product");
NodeList nodes = (NodeList) expression.evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < nodes.getLength(); i++) {
Node product = nodes.item(i);
NodeList productChildren = product.getChildNodes();
for (int j = 0; j < productChildren.getLength(); j++) {
Node item = productChildren.item(j);
if (item instanceof Element) {
Element element = (Element) item;
switch (element.getTagName()) {
case "image":
System.out.println("product image title : " + element.getAttribute("title"));
break;
case "size":
System.out.println("product size : " + element.getTextContent());
break;
default:
break;
}
}
}
}
}
}
我遇到的问题是我必须使用我工作的公司的提供商发送给我的 xml 文件。
如果 xml 构造良好但根本不是问题。
<catalog>
<product>
<ref>4780</ref>
.
.
.
<arrivals>
<product>
<image title="AMARILLO">AMA</image>
<size>S/T </size>
</product>
<product>
<image title="AZUL">AZUL</image>
<size>S/T </size>
</product>
</arrivals>
</product>
</catalog>
如您所见,标签<product>
包含了产品的所有信息,但还有更多名为<product>
的标签,以便在颜色不同时进行区分。
这是我用来在 xml.
doc = db.parse("filename.xml");
Element esproducte = (Element)doc.getElementsByTagName("product").item(0);
NodeList nArrv = esproducte.getElementsByTagName("arrivals");
Element eArrv = (Element) nArrv.item(0);
NodeList eProds = eArrv.getElementsByTagName("product");//THIS THING
for(int l=0; l<eProds.getLength(); l++)
{
Node ln = eProds.item(l);
if (ln.getNodeType() == Node.ELEMENT_NODE)
{
Element le = (Element) ln;
//COLORS / IMAGES / CONFIGS
NodeList nimgcol = le.getElementsByTagName("image");
Element eimgcol = (Element) nimgcol.item(0);
System.out.println("Name of the color " + eimgcol.getTextContent());
}
实际情况是打印重复了更多次,我认为这是因为父 <product>
。我认为这不应该发生,因为我在写 //THIS THING
的地方考虑到了 <product>
设置在 <arrivals>
中的事实。但它不起作用。
我应该在代码中修改什么以在 for 中仅移动 2 次而不是 3 次,这是在这种情况下发生的情况?
解法:
NodeList eProds = eArrv.getElementsByTagName("product");//THIS THING
到
NodeList eProds = eArrv.getChildNodes();//THIS THING
其他的完全一样。完美运行。
完全 有效 在不同的父元素中添加标签,这些元素的名称相同,但具有不同的 content/meaning,就像您的示例中的情况一样。
路径为 /catalog/product
的元素与路径为 /catalog/product/arrivals/product
的元素完全不同。例如,XPath 和 XML Schema 将认为它们是不同的。
只是懒惰写的代码无法区分差异,例如通过使用 getElementsByTagName
,它将元素定位到任何位置 ("all descendants") 而不管位置(路径)。
处理 DOM 树时,以结构化方式进行:
- 迭代根 (
catalog
) 的所有子元素(不是所有后代)。 - 根据严格性,如果元素未命名则失败
product
. - 对于名为
product
的每个元素:- 迭代
product
元素的所有子元素。 - 按名称处理元素,例如
ref
,arrivals
. - 如果严格,如果元素名称未知则失败。
- 如果元素名称是
arrivals
:- 迭代
arrivals
元素的所有子元素。 - 如果严格,如果元素未命名则失败
product
. - 对于名为
product
的每个元素:- 按名称处理元素,例如
image
,size
. - 如果严格,如果元素名称未知则失败。
- 按名称处理元素,例如
- 迭代
- 迭代
如您所见,代码中在名为 catalog
的元素内处理名为 product
的元素的位置与在名为 product
的元素内处理名为 product
的元素的代码不同名为 arrivals
.
getElementsByTagName
为您提供该标签内名称为 "product" 的所有标签,包括颜色的 "product" 标签。
尝试使用 getChildNodes
并改为检查节点的名称
正如 Andreas 所提到的,文档没有任何无效之处,问题在于使用 getElementsByTagName,它只是扫描整个文档以查找具有该标签名称的任何元素,而不管结构如何。
您可以使用 XPath 来简化特定元素的遍历。
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.*;
import java.io.IOException;
import java.io.StringReader;
public class XMLParsing {
public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException, XPathExpressionException {
String xml = "<catalog>\n" +
" <product>\n" +
" <ref>4780</ref>\n" +
" .\n" +
" .\n" +
" .\n" +
" <arrivals>\n" +
" <product>\n" +
" <image title=\"AMARILLO\">AMA</image>\n" +
" <size>S/T </size>\n" +
" </product>\n" +
" <product>\n" +
" <image title=\"AZUL\">AZUL</image>\n" +
" <size>S/T </size>\n" +
" </product>\n" +
" </arrivals>\n" +
" </product>\n" +
"</catalog>\n";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new InputSource(new StringReader(xml)));
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
// get all products under "arrivals"
XPathExpression expression = xPath.compile("/catalog/product/arrivals//product");
NodeList nodes = (NodeList) expression.evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < nodes.getLength(); i++) {
Node product = nodes.item(i);
NodeList productChildren = product.getChildNodes();
for (int j = 0; j < productChildren.getLength(); j++) {
Node item = productChildren.item(j);
if (item instanceof Element) {
Element element = (Element) item;
switch (element.getTagName()) {
case "image":
System.out.println("product image title : " + element.getAttribute("title"));
break;
case "size":
System.out.println("product size : " + element.getTextContent());
break;
default:
break;
}
}
}
}
}
}