当前位置: 首页 > 知识库问答 >
问题:

使用Xpath表达式和jaxb解组XML

滕夜洛
2023-03-14

我是JAXB新手,想知道是否有一种方法可以使用xpath表达式将XML解组到响应对象。问题是我正在呼叫第三方Web服务,我收到的回复有很多详细信息。我不希望将XML中的所有细节映射到我的响应对象。我只希望映射xml中的一些细节,使用特定的XPath表达式可以获得这些细节,并将其映射到响应对象。有没有注释可以帮助我实现这一点?

例如,考虑以下响应

<root>
  <record>
    <id>1</id>
    <name>Ian</name>
    <AddressDetails>
      <street> M G Road </street>
    </AddressDetails>
  </record>  
</root>

我只对检索街道名称感兴趣,所以我想使用xpath表达式使用“root/set/Address详情/street”获取街道值并将其映射到我的响应对象

public class Response{
     // How do i map this in jaxb, I do not wish to map record,id or name elements
     String street; 

     //getter and setters
     ....
}   

谢啦

共有3个答案

薛弘阔
2023-03-14

如果要映射到XML文档的中间,可以执行以下操作:

演示代码

您可以使用StAX解析器前进到您希望散集的文档部分,然后从那里散集XMLStreamReader

import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Response.class);

        XMLInputFactory xif = XMLInputFactory.newFactory();
        StreamSource xml = new StreamSource("src/forum17141154/input.xml");
        XMLStreamReader xsr = xif.createXMLStreamReader(xml);
        while(!(xsr.isStartElement() && xsr.getLocalName().equals("AddressDetails"))) {
            xsr.next();
        }

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        JAXBElement<Response> response = unmarshaller.unmarshal(xsr, Response.class);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(response, System.out);
    }

}

回应

域对象上的映射是相对于要映射到的XML文档的片段进行的。

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class Response{

    String street; 

    //getter and setters
}

输出

<?xml version="1.0" encoding="UTF-8"?>
<AddressDetails>
   <street> M G Road </street>
</AddressDetails>

有关更多信息

  • http://blog.bdoughan.com/2012/08/handle-middle-of-xml-document-with-jaxb.html
云英才
2023-03-14

如果您只需要街道名称,只需使用XPath表达式将其作为字符串,并且忘记JAXB——复杂的JAXB机制不会增加任何价值。

import javax.xml.xpath.*;
import org.xml.sax.InputSource;

public class XPathDemo {

    public static void main(String[] args) throws Exception {
        XPathFactory xpf = XPathFactory.newInstance();
        XPath xpath = xpf.newXPath();

        InputSource xml = new InputSource("src/forum17141154/input.xml");
        String result = (String) xpath.evaluate("/root/record/AddressDetails/street", xml, XPathConstants.STRING);
        System.out.println(result);
    }

}
洪伟彦
2023-03-14

注意:我是Eclipse Link JAXB(MOXy)负责人,也是JAXB(JST-222)专家组的成员。

对于这个用例,您可以使用MOXy的XmlPath扩展。

回应

import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement(name="root")
@XmlAccessorType(XmlAccessType.FIELD)
public class Response{
    @XmlPath("record/AddressDetails/street/text()")
    String street; 

    //getter and setters
}

jaxb.properties

要使用MOXy作为JAXB提供程序,需要包含一个名为JAXB的文件。属性与域模型位于同一个包中,具有以下条目(请参阅:http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html)

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

演示

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Response.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum17141154/input.xml");
        Response response = (Response) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(response, System.out);
    }

}

输出

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <record>
      <AddressDetails>
         <street> M G Road </street>
      </AddressDetails>
   </record>
</root>

有关更多信息

  • http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
  • http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
 类似资料:
  • 问题内容: 我是JAXB的新手,并且想知道是否有一种方法可以使用xpath表达式将XML解组到我的响应对象。问题是我正在呼叫第三方Web服务,收到的响应有很多详细信息。我不希望将XML中的所有详细信息映射到我的响应对象。我只希望从xml映射一些细节,使用这些细节我可以使用特定的XPath表达式并将其映射到我的响应对象。有没有注释可以帮助我实现这一目标? 例如考虑以下响应 我只对检索街道名称感兴趣,

  • 主要内容:示例XPath表达式通常定义模式以便选择一组节点。 这些模式由XSLT用于执行转换,或者由用于寻址。 XPath规范指定了七种类型的节点,这些节点可以是XPath表达式的执行输出。 根 元素 文本 属性 注释 处理指令 命名空间 XPath使用路径表达式从XML文档中选择节点或节点列表。 以下是从XML文档中选择节点/节点列表的路径和表达式列表。 序号 表达式 描述 1 选择具有给定名称的所有节点。

  • 问题内容: 我有一个返回此XML的服务: 要么 我想使用以下类解组检索到的XML: 结果 : 项目名称 : 用户名 : 首先不起作用的解决方案 我得到一个空名单。 第二不起作用的解决方案 受本文启发,http://blog.bdoughan.com/2012/11/creating-generic-list-wrapper-in- jaxb.html 我修改了Response类: 然后使用以下代码

  • 编辑:感谢Preetam Kumar,这个问题已经解决,但错误现在在其他地方。当我再次尝试解组我的xml文件时,我收到这个错误,告诉我找不到元素: 然而,我给了xml文件到模式的正确路径,但是它似乎没有使用它...我不明白。 注意:我知道模式和xml标记在下面的示例中不完全匹配,我已经在我的文件中纠正了它。 最近,我不得不使用JAXB java库将一些XML文件解析为java对象。 我制作了一个X

  • 问题内容: 我正在尝试创建一个非常简单的REST服务器。我只是有一个测试方法,它将返回字符串列表。这是代码: 它给出以下错误: 我希望JAXB对诸如String,Integer等简单类型具有默认设置。我想不是。这是我的想象: 使这种方法最简单的方法是什么? 问题答案: 我使用@LiorH的示例并将其扩展为: 注意,它使用泛型,因此您可以将其与String之外的其他类一起使用。现在,应用程序代码很简

  • 问题内容: 我正在使用这样的构造: 但是我需要选择所有以“某些文本”开头的文本的链接,所以我想知道这里是否可以使用regexp?在lxml文档中找不到任何内容 问题答案: 您可以执行此操作(尽管该示例不需要正则表达式)。Lxml支持来自EXSLT扩展功能的正则表达式。(请参阅XPath类的lxml文档,但该方法也适用于该方法) 请注意,您需要提供名称空间映射,以便它知道xpath表达式中的“ re