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
我正在解析一个 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