xml DOM- 换行符在 java DOM 解析器中添加两次 text/attribute 内容

xml DOM- Newline adds the text/attribute content twice in java DOM parser

我正在解析一个 XML 文件。我开发了一个从 xml 文件读取数据的 swing 应用程序。它根据 subject 中设置的 subject 值在 comboBxCh 中添加 chapters =]comboBxSb。 代码如下:

Java代码:

public void loadChapters(JComboBox comboBxCh, JComboBox comboBxSb)
{
    tempList = xmlDoc.getElementsByTagName("subject");
    NodeList secNodeList = null;
    Element ele=null;
    int i, j, totalElements;
    totalElements = tempList.getLength();
    i = j =0;
    for(i=0;i<totalElements;i++)
    {
        secNodeList = tempList.item(i).getChildNodes();
        for(j=0;j<secNodeList.getLength();j++)
        {
            if(secNodeList.item(j).getNodeType()==Node.ELEMENT_NODE)
            {   
                ele = (Element)secNodeList.item(j);
            }

            if(ele!=null && ele.getTagName()=="sname" && ele.getTextContent()==comboBxSb.getSelectedItem().toString() )
            {
                for(i=0;i<secNodeList.getLength();i++)
                {
                    if(secNodeList.item(i).getNodeType()==Node.ELEMENT_NODE)
                        ele = (Element)secNodeList.item(i);
                    if(ele.getTagName()=="chapter") //Adding it solves my problem-> &&i%2==1
                    {
                            comboBxCh.addItem(ele.getAttribute("name"));
                    }
                }
                return;
            }
        }
    }
}

XML代码:

<subjects>
    <subject id="1">
        <sname>Quantitave Aptitude</sname>
        <chapter name="Number series"/>
        <chapter name="Time and work"/>
        <chapter name="Trains and rivers"/>
    </subject>
    <subject id="2">
        <sname>English</sname>
        <chapter name="Articles"/>
        <chapter name="Nouns"/>
        <chapter name="Comprehension text"/>
    </subject>
    <subject id="3">
        <sname>Logical Reasoning</sname>
        <chapter name="What's next"/>
        <chapter name="Next figure"/>
        <chapter name="Series"/>
    </subject>
    <subject id="4">
        <sname>GK</sname>
    </subject>
</subjects>

当加载 swing 应用程序时,comboBxSb 包含所有四个科目,定量能力id="1")保持选中 开始,因此它的三章载入 comboBxCh。但是它的每一章加载两次!在 xml 文件中,如果我从每一行的章节名称之间删除 \n,则不会发生重复。即 ->

    <subject id="1">
        <sname>Quantitave Aptitude</sname>
        <chapter name="Number series"/><chapter name="Time and work"/><chapter name="Trains and rivers"/>
    </subject>

。 /------------------------------------/

有申请截图:

不修改 XML 的解决方案已在评论中提及。 那是我只能添加奇数(或偶数)否。 但我的问题是 为什么会这样? 如果我将章节名称作为 文本内容 也会发生这种情况在 <chapter> </chapter> 标签和使用 'getTextContent()`

提取的文本之间

很难 100% 确定,因为您只提供了一个脱离上下文的代码片段,但我的 "guess" 是您没有清除任何先前的 JComboBox值。

尽管如此,您的 loadChapters 方法可以做得更好。相反,您可以使用 xpath API 来查询 XML 文档和 return 仅查询您真正想要的那些值,就像您可能对数据库所做的那样,例如...

public static List<String> loadChapters(Document xmlDoc, String name) throws XPathExpressionException {
    List<String> results = new ArrayList<>(25);
    XPathFactory xf = XPathFactory.newInstance();
    XPath xPath = xf.newXPath();

    String query = "/subjects/subject[sname[text()='" + name + "']]/chapter/@name";
    XPathExpression xExp = xPath.compile(query);
    NodeList nl = (NodeList) xExp.evaluate(xmlDoc, XPathConstants.NODESET);
    for (int index = 0; index < nl.getLength(); index++) {
        Node node = nl.item(index);
        results.add(node.getNodeValue());
    }
    return results;
}

使用类似...

try {
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    Document doc = dbf.newDocumentBuilder().parse(new File("Test.xml"));
    List<String> chapters = loadChapters(doc, "Quantitave Aptitude");
    for (String chapter : chapters) {
        System.out.println(chapter);
    }
} catch (ParserConfigurationException | SAXException | IOException | XPathExpressionException exp) {
    exp.printStackTrace();
}

这会打印...

Number series
Time and work
Trains and rivers

因此我们可以确保 loadChapters 方法不会 return 重复。

现在为了让您的生活更轻松,您可以创建一个由 List 支持的自定义 ComboBoxModel...

public class ListComboBoxModel<E> extends AbstractListModel<E> implements MutableComboBoxModel<E> {

    private List<E> values;
    private Object selectedItem;

    public ListComboBoxModel() {
        this.values = new ArrayList<>(25);
    }

    public ListComboBoxModel(List<E> values) {
        this.values = new ArrayList<>(values);
    }

    @Override
    public int getSize() {
        return values.size();
    }

    @Override
    public E getElementAt(int index) {
        return values.get(index);
    }

    @Override
    public void addElement(E item) {
        values.add(item);
    }

    @Override
    public void removeElement(Object obj) {
        values.remove((E)obj);
    }

    @Override
    public void insertElementAt(E item, int index) {
        values.add(index, item);
    }

    @Override
    public void removeElementAt(int index) {
        values.remove(index);
    }

    @Override
    public void setSelectedItem(Object anItem) {
        selectedItem = anItem;
    }

    @Override
    public Object getSelectedItem() {
        return selectedItem;
    }

}

因此您可以使用类似...

ComboBoxModel<String> model = new ListComboBoxModel<String>(loadChapters(doc, "Quantitave Aptitude"));

然后将新模型直接应用到 JComboBox