Java 为什么我不能在线程中正确删除带有循环的JDOM节点?

Java 为什么我不能在线程中正确删除带有循环的JDOM节点?,java,jdom,Java,Jdom,我知道为什么我下面的代码会提出一个问题,xml文件中的一些节点并没有像应该删除的那个样被删除 我需要维护一个java应用程序,这个应用程序的目的是比较两个PDF文件。应用程序从两台服务器提取xml文件中的数据;然后删除两个xml文件中的一些节点以忽略某些部分,最后应用程序将两个处理过的xml文件发送回两个服务器以获取PDF文件,并提取PDF文件以进行字节比较。应用程序使用JDOMAPI来解析和操作xml文件 这是我的密码: /** * Ignores all Changes of this F

我知道为什么我下面的代码会提出一个问题,xml文件中的一些节点并没有像应该删除的那个样被删除

我需要维护一个java应用程序,这个应用程序的目的是比较两个PDF文件。应用程序从两台服务器提取xml文件中的数据;然后删除两个xml文件中的一些节点以忽略某些部分,最后应用程序将两个处理过的xml文件发送回两个服务器以获取PDF文件,并提取PDF文件以进行字节比较。应用程序使用JDOMAPI来解析和操作xml文件

这是我的密码:

/**
 * Ignores all Changes of this Form
 */
@SuppressWarnings("rawtypes")
protected void ignoreChangesSection() {
    Element formNumberElement=retrieveElement(getSiapXmlDocument(), FORM_REQUESTED_ELEMENT).getChild(FORM_NUMBER_ELEMENT);
    String formNumber=formNumberElement.getText();



    /*retrieveElement(getSiapXmlDocument(), DATA_ELEMENT).getChild(APPROACH_RESOURCE_INSTANCE_ELEMENT).
                                          getChild(APPROACH_ELEMENT).removeChildren(CHANGES_ELEMENT);*/

    Element approachElement = 
        retrieveElement(getSiapXmlDocument(), DATA_ELEMENT).getChild(APPROACH_RESOURCE_INSTANCE_ELEMENT).
                                      getChild(APPROACH_ELEMENT);

    List changeReasonList1 = approachElement.getChildren(CHANGES_ELEMENT);

    if (changeReasonList1!=null)
    {           
        for (int i=0; i<changeReasonList1.size(); i++)
        {
            Element chngRsn = (Element)changeReasonList1.get(i);

            String ind = chngRsn.getChildText(REASON_CHANGE_IND);

            if (ind != null && !"".equals(ind))
            {

                if (ind.equals(CHANGE) || (formNumber.equals("8260-7A") && ind.equals(CHANGE_FORM_7A)))
                {

                    chngRsn.detach();
                }
            }
        }
    }

}
/**
*忽略此表单的所有更改
*/
@抑制警告(“原始类型”)
受保护的无效IgnoreChangeSection(){
元素formNumberRelement=retrieveElement(getSiapXmlDocument(),FORM_REQUESTED_元素)。getChild(FORM_NUMBER_元素);
字符串formNumber=formnumberrelation.getText();
/*retrieveElement(getSiapXmlDocument(),数据元素).getChild(方法资源实例元素)。
getChild(接近元素)。removeChildren(更改元素)*/
元素接近元素=
retrieveElement(getSiapXmlDocument(),数据元素).getChild(方法资源实例元素)。
getChild(接近元素);
List changeReasonList1=approachElement.getChildren(CHANGES\u元素);
if(changeReasonList1!=null)
{           

对于(int i=0;i),当您分离节点时,也将列表的大小减少一个……考虑一个四个节点的列表,A、B、B、C.</P> 是否要删除/分离B节点

在循环中,您迭代并从0开始,然后移动到1…删除节点1。但是,现在您的列表是:A、B、C,索引是1。然后再次循环,索引是2,指向C,然后退出循环

不删除第二个节点B

这是一个通用的计算错误,在列表中循环时,您无法轻松地从列表中删除节点

Java提供了一个迭代器,JDOM也实现了这个迭代器,这将是您正确的选择…现在,您应该使用JDOM 2.x而不是JDOM 1.x。2会更容易,但是,即使使用JDOM 1…使用迭代器:

for (Iterator it = changeReasonList1.iterator(); it.hasNext();) {
    Element chngRsn = (Element)it.next();
    if (various reasons) {
        // detach the element:
        it.remove();
    }
}
编辑、更新评论:

两个关键点是:

  • emt.detach()
  • approachElement.getChildren(…)
    返回一个“活动”列表。对列表的更改反映在元素中,反之亦然
  • 因此,当您在luve列表中循环并将
    emt
    作为索引
    get(…)
    获取时,您将获得一个子元素。当您分离该子元素时,您将断开它与父元素的连接,从而也将该子元素从
    approachElement
    列表中移除。该列表将缩小一

    所以,你的循环:

    for (int i=0; i<changeReasonList1.size(); i++)
    
    本质上,你也在做:

    changeReasonList1.remove(i);
    
    这是关键点……您实际上是在列表循环中执行remove(i)。如果您将JDOM从等式中去掉,则情况更简单:

    List<Integer> data = new ArrayList<>();
    data.add(1);
    data.add(2);
    data.add(3);
    
    for (int i = 0; i < data.size(); i++) {
        System.out.println("before: " + data.get(i));
        if (i == 1) {
            data.remove(i);
        }
        System.out.println("after: " + data.get(i));
    }
    
    然后退出

    因此,它永远不会“测试”before值
    3
    ,因为在删除
    2
    ,我们会缩小列表,最后一个循环的大小是2,循环中的索引增加到2,因此循环终止


    迭代器避免了这种情况。

    您好,非常感谢您的帮助!它很有效!我会理解为什么我在以前的代码中分离了错误的节点。我没有使用任何索引作为分离参数;我获取第I个元素并决定是否删除它,如果我应该删除此节点,我使用分离。当我在调试模式下跟踪时,我注意到如果拆离一个节点,列表会缩小,我认为我正在拆离正确的节点,否则控制流无法到达“拆离”。那么为什么会出现此问题?如果您能给我更多提示,我将不胜感激。请编辑以包含更多细节
    List<Integer> data = new ArrayList<>();
    data.add(1);
    data.add(2);
    data.add(3);
    
    for (int i = 0; i < data.size(); i++) {
        System.out.println("before: " + data.get(i));
        if (i == 1) {
            data.remove(i);
        }
        System.out.println("after: " + data.get(i));
    }
    
    before: 1
    after: 1
    before: 2
    after: 3