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 的元素完全不同。例如,XPathXML 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;
                    }
                }
            }
        }
    }
}