如何循环遍历 JAXB 类,如果同一 XML 节点不止一层
How to Loop through JAXB classes, if there are more than one level of same XML node
这是我实际 XML 的最漂亮版本(我没有 XSD,也不会从源系统中获得它)
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<!--Java Class Comp.java-->
<Comp>
<Name>Component Name</Name>
<Available_Start_Date>2018-07-10</Available_Start_Date>
<!--Java Class P_to_P.java-->
<P_to_P>
<Max>1</Max>
<Min>1</Min>
<!-- Java Class P.java-->
<P>
<Name>Composite</Name>
<P_to_P>
<Max>1</Max>
<Min>1</Min>
<P>
<Name>Another Level</Name>
</P>
</P_to_P>
<P_to_P>
<Max>1</Max>
<Min>1</Min>
<P>
<Name>Yet Another Level</Name>
</P>
</P_to_P>
</P>
</P_to_P>
</Comp>
</Root>
现在,如果我开始为其编写 JAXB 类(手动并使用 IDE),我必须为我正在经历的每个级别编写 for 循环。现在,这个 XML 中的 child 可能显示为 child 的 Parent(P_to_P 有 P 作为 child 而 P 有 P_to_P 为 child,并且 parent-child 关系的深度可以是任意数量的级别。
因此,如果我编写一个 Main JAXB 文件,那么我是否必须在 for 循环中编写那么多 for 循环以遍历所有 Parent 和 Child?还是有更好的方法来实现?
您可以像这样编写您的 POJO 类 P
和 P_to_P
:
@XmlAccessorType(XmlAccessType.FIELD)
public class P_to_P {
@XmlElement(name = "Max")
private int max;
@XmlElement(name = "Min")
private int min;
@XmlElement(name = "P")
private P p;
// public getters and setters (omitted for brevity)
}
@XmlAccessorType(XmlAccessType.FIELD)
public class P {
@XmlElement(name = "Name")
private String name;
@XmlElement(name = "P_to_P")
private List<P_to_P> pToPList;
// public getters and setters (omitted for brevity)
}
然后你能遍历整个树并像下面这样处理每个项目吗?
注意递归:方法 process(P_to_P)
调用 process(P)
,
方法 process(P)
调用 process(P_to_P)
。
还要注意检查 null
以防止 NullPointerException
并终止递归。
public static void main(String[] args) {
File file = new File("root.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jaxbCntext.createUnmarshaller();
Root root = (Root) unmarshaller.unmarshal(file);
P_to_P pToP = root.getComp().getPToP();
process(pToP);
}
private static void process(P_to_P pToP) {
if (pToP == null)
return;
// do anything you like here
process(pToP.getP());
}
private static void process(P p) {
if (p == null)
return;
// do anything you like here
if (p.getpToPList() == null)
return;
for (P_to_P pToP : p.getpToPList()) {
process(pToP);
}
}
这是我实际 XML 的最漂亮版本(我没有 XSD,也不会从源系统中获得它)
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<!--Java Class Comp.java-->
<Comp>
<Name>Component Name</Name>
<Available_Start_Date>2018-07-10</Available_Start_Date>
<!--Java Class P_to_P.java-->
<P_to_P>
<Max>1</Max>
<Min>1</Min>
<!-- Java Class P.java-->
<P>
<Name>Composite</Name>
<P_to_P>
<Max>1</Max>
<Min>1</Min>
<P>
<Name>Another Level</Name>
</P>
</P_to_P>
<P_to_P>
<Max>1</Max>
<Min>1</Min>
<P>
<Name>Yet Another Level</Name>
</P>
</P_to_P>
</P>
</P_to_P>
</Comp>
</Root>
现在,如果我开始为其编写 JAXB 类(手动并使用 IDE),我必须为我正在经历的每个级别编写 for 循环。现在,这个 XML 中的 child 可能显示为 child 的 Parent(P_to_P 有 P 作为 child 而 P 有 P_to_P 为 child,并且 parent-child 关系的深度可以是任意数量的级别。
因此,如果我编写一个 Main JAXB 文件,那么我是否必须在 for 循环中编写那么多 for 循环以遍历所有 Parent 和 Child?还是有更好的方法来实现?
您可以像这样编写您的 POJO 类 P
和 P_to_P
:
@XmlAccessorType(XmlAccessType.FIELD)
public class P_to_P {
@XmlElement(name = "Max")
private int max;
@XmlElement(name = "Min")
private int min;
@XmlElement(name = "P")
private P p;
// public getters and setters (omitted for brevity)
}
@XmlAccessorType(XmlAccessType.FIELD)
public class P {
@XmlElement(name = "Name")
private String name;
@XmlElement(name = "P_to_P")
private List<P_to_P> pToPList;
// public getters and setters (omitted for brevity)
}
然后你能遍历整个树并像下面这样处理每个项目吗?
注意递归:方法 process(P_to_P)
调用 process(P)
,
方法 process(P)
调用 process(P_to_P)
。
还要注意检查 null
以防止 NullPointerException
并终止递归。
public static void main(String[] args) {
File file = new File("root.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jaxbCntext.createUnmarshaller();
Root root = (Root) unmarshaller.unmarshal(file);
P_to_P pToP = root.getComp().getPToP();
process(pToP);
}
private static void process(P_to_P pToP) {
if (pToP == null)
return;
// do anything you like here
process(pToP.getP());
}
private static void process(P p) {
if (p == null)
return;
// do anything you like here
if (p.getpToPList() == null)
return;
for (P_to_P pToP : p.getpToPList()) {
process(pToP);
}
}