使用 JAXB 获取 XML 子节点的值

Posted

技术标签:

【中文标题】使用 JAXB 获取 XML 子节点的值【英文标题】:getting the value of an XML subnode using JAXB 【发布时间】:2021-10-23 04:42:43 【问题描述】:

我正在尝试使用 JAXB 映射此 XML 文件并获取 CODE 元素的值。最终,完整的 XML 文件将包含许多收费代码块,我需要提取不同标签的所有值,但现在我只想设法获得一个值。

XML:

<?xml version="1.0" encoding="utf-8" ?>
<tpDoc>
  <tpCTRL>
      <DocID>CHARGE CODES</DocID>
      <SenderID>IES</SenderID>
  </tpCTRL>
  <PAYLOAD>
   <CHARGE_CODE>
    <CODE>TEST</CODE>
    <DESCRIPTION>M Test</DESCRIPTION>
    <SALES_ACCOUNT>34535</SALES_ACCOUNT>
    <COSTS_ACCOUNT>500056756745</COSTS_ACCOUNT>
   </CHARGE_CODE>
  </PAYLOAD>
</tpDoc>

这是编组代码:

public class XMLtoJava 

    public static void main(String[] args) throws JAXBException 
        File inputFile = new File("C:\\Users\\Inbar\\OneDrive\\OneDrive - alfacloud.co.il\\MSF\\Developments\\OrdertoCashThirdPartyProcess(B2B)\\MSF XMLFiles\\ChargeCodesSmall.XML");

        JAXBContext jaxbContext = JAXBContext.newInstance(CC.class);

        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        CC chargeCode =  (CC) unmarshaller.unmarshal(inputFile);
        System.out.println();
        System.out.println(chargeCode.getCode());
    

班级:

@XmlRootElement(name="tpDoc")
@XmlAccessorType(XmlAccessType.FIELD)
public class CC 

    @XmlElement(name="CODE")
    private String code;
    @XmlElement(name="DESCRIPTION")
    private String description;
    @XmlElement(name="SALES_ACCOUNT")
    private String salesAccount;
    @XmlElement(name="COSTS_ACCOUNT")
    private String costsAccount;


    public String getCode() 
        return code;
    

但是,我得到的只是空值。我做错了什么?

【问题讨论】:

tpDoc 没有您在CC 中指定的字段。它有一个PAYLOAD,其中包含一个CODE 和其他元素。换句话说,您在CC 中的定义与 XML 结构不匹配。 @MarkRotteveel 那么我想以某种方式创建另一个名为 payload 的类还是我可以以某种方式告诉这个 tpdoc 类正确的子结构?换句话说,在创建尽可能少的类的同时,我该怎么做才能解决这个问题。 您可以使用this 等在线工具将示例XML 文件转换为XSD。然后您可以使用xjc 工具(与Java 8 捆绑在一起,或者也可以使用here)使用该XSD 来生成表示XML 结构所需的Java 类。 建议:在生成 Java 类时,请确保您的示例 XML 包含多个 &lt;CHARGE_CODE&gt; 部分,因为这最终是您需要的,并且与 XML 相比,这将改变 Java 的结构只有一个 &lt;CHARGE_CODE&gt; 条目的示例。 【参考方案1】:

这应该对你有用,你应该能够得到任何值。我已将Project Lombok 用于Getter and Setter methods。另外,跳过了tpCTRL 的 POJO,您需要添加它们

XML:

<?xml version="1.0" encoding="utf-8" ?>
<tpDoc>
    <tpCTRL>
        <DocID>CHARGE CODES</DocID>
        <SenderID>IES</SenderID>
    </tpCTRL>
    <PAYLOAD>
        <CHARGE_CODE>
            <CODE>TEST</CODE>
            <DESCRIPTION>M Test</DESCRIPTION>
            <SALES_ACCOUNT>34535</SALES_ACCOUNT>
            <COSTS_ACCOUNT>500056756745</COSTS_ACCOUNT>
        </CHARGE_CODE>
    </PAYLOAD>
</tpDoc>

tpDoc:

@XmlRootElement(name = "tpDoc")
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class tpDoc 
    @XmlElement(name="PAYLOAD")
    private Payload payload;


有效载荷;

@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class Payload 
    @XmlElement(name="CHARGE_CODE")
    private ChargeCode chargeCode;

收费代码;

@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class ChargeCode 
    private String CODE;
    private String DESCRIPTION;
    private String SALES_ACCOUNT;
    private String COSTS_ACCOUNT;


主要:

public class Main 
    public static void main(String[] args) throws JAXBException, XMLStreamException 
        final InputStream inputStream = Main.class.getClassLoader().getResourceAsStream("sample.xml");
        final XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
        final Unmarshaller unmarshaller = JAXBContext.newInstance(tpDoc.class).createUnmarshaller();
        final tpDoc tpDoc = unmarshaller.unmarshal(xmlStreamReader, tpDoc.class).getValue();
        System.out.println(tpDoc.toString());
        System.out.println(tpDoc.getPayload().getChargeCode().getCODE());
        System.out.println(tpDoc.getPayload().getChargeCode().getCOSTS_ACCOUNT());

        Marshaller marshaller = JAXBContext.newInstance(tpDoc.class).createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.marshal(tpDoc, System.out);
    

下面是输出;

tpDoc(payload=Payload(chargeCode=ChargeCode(CODE=TEST, DESCRIPTION=M Test, SALES_ACCOUNT=34535, COSTS_ACCOUNT=500056756745)))
TEST
500056756745
<tpDoc>
   <PAYLOAD>
      <CHARGE_CODE>
         <CODE>TEST</CODE>
         <DESCRIPTION>M Test</DESCRIPTION>
         <SALES_ACCOUNT>34535</SALES_ACCOUNT>
         <COSTS_ACCOUNT>500056756745</COSTS_ACCOUNT>
      </CHARGE_CODE>
   </PAYLOAD>
</tpDoc>

【讨论】:

伟大的 sutff,谢谢。我想知道。如果我需要将我提取的值用于其他事情,比如验证与数据库等等......我是否在解组类中为这些数据编写 getter 以用于其他包? @Data 每个类的注释来自Project Lombok,它具有GetterSetter,因此如果您使用Poject Lombok,则无需编写任何额外的Getter在各自的POJO Classes 上使用@Data。乐意效劳。如果对您有帮助,请点赞并接受答案。 也接受答案?您需要做的就是点击我的答案旁边的CHECK 按钮,然后点击我的答案旁边的^ 符号:***.com/help/someone-answers

以上是关于使用 JAXB 获取 XML 子节点的值的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 JAXB xml 解析获取特定元素?

java获取XML指定节点的全部子节点

Codeforces 486D Valid Sets

怎样获取xml中当前节点的直接孩子节点个数

java 如何读取xml文件中的一个节点下的多个相同子节点

当节点包含值时,使用 JAXB 将 XML 转换为对象