【问题标题】:Java. Moving in a xml with the same tag name as child爪哇。移入与子标签名称相同的 xml
【发布时间】:2015-08-28 05:35:35
【问题描述】:

我遇到的问题是我必须使用我工作的公司的供应商发送给我的 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>

如您所见,标签&lt;product&gt;包含了产品的所有信息,但名称为&lt;product&gt;的标签更多,以区分不同的颜色。
这是我用来在 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());
}

发生的情况是打印重复了更多次,我认为这是因为父 &lt;product&gt;。我认为这不应该发生,因为我写//THIS THING 的地方我考虑到&lt;product&gt; 设置在&lt;arrivals&gt; 中的事实。但它不起作用。
我应该在代码中修改什么以在 for 中只移动 2 次而不是 3 次,在这种情况下会发生什么?

解决办法:

NodeList eProds = eArrv.getElementsByTagName("product");//THIS THING

NodeList eProds = eArrv.getChildNodes();//THIS THING

其余的完全一样。完美运行。

【问题讨论】:

    标签: java xml tags element parent


    【解决方案1】:

    getElementsByTagName 为您提供该标签内名称为“产品”的所有标签,包括用于颜色的“产品”标签。 尝试使用getChildNodes 并改为检查节点的名称

    【讨论】:

      【解决方案2】:

      在名称相同但内容/含义不同的不同父元素中包含标签是完全有效的,就像您的示例中的情况一样。

      路径为/catalog/product 的元素与路径为/catalog/product/arrivals/product 的元素完全不同。例如,XPathXML Schema 都会认为它们是不同的。

      只有懒惰编写的代码无法区分差异,例如通过使用getElementsByTagName,它将元素定位在任何位置(“所有后代”),而不管位置(路径)。

      在处理 DOM 树时,以结构化的方式进行:

      • 迭代根 (catalog) 的所有子元素(不是所有后代)。
      • 取决于严格性,如果元素未命名为 product,则失败。
      • 对于每个名为 product 的元素:
        • 迭代product元素的所有子元素。
        • 按名称处理元素,例如refarrivals
        • 如果严格,如果元素名称未知则失败。
        • 如果元素名称是arrivals
          • 迭代arrivals元素的所有子元素。
          • 如果严格,如果元素未命名则失败product
          • 对于每个名为 product 的元素:
            • 按名称处理元素,例如image, size.
            • 如果严格,如果元素名称未知则失败。

      如您所见,处理名为 catalog 的元素内名为 product 的元素的代码与处理名为 arrivals 的元素内的名为 product 的元素的代码不同。

      【讨论】:

        【解决方案3】:

        正如 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;
                            }
                        }
                    }
                }
            }
        }
        

        【讨论】:

        • 我假设您只想在 arrivalsproduct 之间有一个 /
        • 该代码不会将所有“目录产品”中的所有“到达产品”迭代为一个平面列表,从而无法跟踪哪些“到达产品”属于 ref=4780 的“目录产品”,如反对属于“目录产品”的“到达产品”,ref=4781(例如)?
        猜你喜欢
        • 2014-01-18
        • 1970-01-01
        • 1970-01-01
        • 2016-12-28
        • 1970-01-01
        • 1970-01-01
        • 2012-03-17
        • 1970-01-01
        • 2018-11-07
        相关资源
        最近更新 更多