【问题标题】:How do I remove the namespace values from my nested XML child elements?如何从嵌套的 XML 子元素中删除命名空间值?
【发布时间】:2013-05-15 19:57:48
【问题描述】:

我有一个由 Jackson、Jersey、EclipseLink 和 Tomcat 提供支持的小型 RESTful Web 服务。在大多数情况下,XML 都按预期工作,但涉及到我的嵌套子元素时除外。当 XML 文档的其余部分没有时,它们是用命名空间属性编写的。这是响应 XML 的示例:

<userView>
    <userIdSID>5</userIdSID>
    <userAuthLevel>5</userAuthLevel>
    <userRoles>
        <roleSID xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:decimal">1</roleSID>
        <roleSID xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:decimal">3</roleSID>
        <roleSID xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:decimal">2</roleSID>
        <roleSID xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:decimal">8</roleSID>
        <roleSID xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:decimal">5</roleSID>
        <roleSID xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:decimal">4</roleSID>
        <roleSID xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:decimal">9</roleSID>
        <roleSID xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:decimal">1000001</roleSID>
    </userRoles>
</userView>

这就是我的 UserRoleList.java 的样子:

package com.company.project;

import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;

@XmlAccessorType(XmlAccessType.FIELD)
public class UserRoleList implements Serializable {

    private int userRoleSID;

    public int getUserRoleSid() {
        return userRoleSID;
    }

    public void setUserRoleSid(int userRoleSid) {
        this.userRoleSID = userRoleSid;
    }
}

这就是我的 UserView.java 的样子:

package com.company.project;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

@Entity
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class UserView implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @Column(name = "USER_ID_SID")
    private String userIdSID;
    @Basic(optional = true)
    private String userAuthLevel;
    @XmlElementWrapper(name = "userRoles")
    @XmlElement(name = "roleSID")
    private List<UserRoleList> userRoleList = new ArrayList<UserRoleList>();

    public UserView() {
    }

    public UserView(String userIdSID) {
        this.userIdSID = userIdSID;
    }

    public String getUserIdSID() {
        return userIdSID;
    }

    public void setUserIdSID(String userIdSID) {
        this.userIdSID = userIdSID;
    }

    public List<UserRoleList> getUserRoleList() {
        return userRoleList;
    }

    public void setUserRoleList(List<UserRoleList> userRoleList) {
        this.userRoleList = userRoleList;
    }

    public String getUserAuthLevel() {
        return userAuthLevel;
    }

    public void setUserAuthLevel(String userAuthLevel) {
        this.userAuthLevel = userAuthLevel;
    }
}

这就是我填充该嵌套元素的方式,它需要 2 个入站参数并通过实体管理器执行查询:

 List<UserRoleList> userRoleList = em.createNamedQuery("findRoleListByLoginName")
                    .setParameter(1, id)
                    .setParameter(2, client)
                    .getResultList();

关于我可能遗漏什么的任何想法?我尝试使用 pkg-info 无济于事。请注意,此输出构造了一个没有从中生成模式的 XML。不确定这是否有帮助或阻碍,但我们将不胜感激。

更新 1:根据要求,这是我的 web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <display-name>moxyWS</display-name>
    <servlet>
        <servlet-name>ServletAdaptor</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <init-param>
            <description>Multiple packages, separated by semicolon(;), can be specified in param-value</description>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>com.project.moxyws</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>ServletAdaptor</servlet-name>
        <url-pattern>/webresources/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
    <persistence-unit-ref>
        <persistence-unit-ref-name>persistence-factory</persistence-unit-ref-name>
        <persistence-unit-name>moxyWS_war_1.0-SNAPSHOTPU</persistence-unit-name>
    </persistence-unit-ref>
</web-app>

更新 2:根据要求,这是我的 REST 外观:

package com.project.moxyws.service;

import com.project.moxyws.UserView;
import com.project.moxyws.controller.UserViewJPAController;
import javax.naming.NamingException;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;

@Path("request")
public class UserViewRESTFacade {

    private EntityManagerFactory getEntityManagerFactory() throws NamingException {
        return (EntityManagerFactory) Persistence
                .createEntityManagerFactory("moxyWS_war_1.0-SNAPSHOTPU");
    }

    private UserViewJPAController getJpaController() {
        try {
            return new UserViewJPAController(getEntityManagerFactory());
        } catch (NamingException ex) {
            throw new RuntimeException(ex);
        }
    }

    public UserViewRESTFacade() {
    }

    @GET
    @Path("{client}/{id}")
    @Produces({"application/xml", "application/json"})
    public UserView findUserByClientAndID(@PathParam("client") String client, @PathParam("id") String id) {
        try {
            return getJpaController().findUserId(id, client);
        } catch (Exception e) {
            throw new WebApplicationException(204);
        }
    }
}

【问题讨论】:

  • 只需将您的代码放入 JAXBContext,然后创建一个编组器,就会为每个角色 SID 输出 &lt;roleSID&gt;&lt;userRoleSID&gt;#&lt;/userRoleSID&gt;&lt;/roleSID&gt;。我想这是您的 Jersey 编组配置、包信息中的设置,或者您没有在代码库中使用这些文件?
  • 添加了 XmlValue 属性,它会吐出正确的输出。仍然看不到你得到的命名空间。
  • 不,我是说他们的默认不应该添加这些命名空间,除非你在某处有设置/配置
  • 如果您需要帮助,请发布您的 web.xml 以及您的球衣端点代码。我不确定您已经发布的代码是您系统中正在使用的代码,因为它需要 @xmlvalue 才能使其没有子元素。

标签: java xml web-services jakarta-ee serialization


【解决方案1】:

我认为问题在于您的 UserRoleList 类,它是一个具有单个字段的类,您确实希望将其映射到一个简单类型。您可能想尝试使用 @XmlValue 注释来注释 userRoleSID 成员。

【讨论】:

  • 我试过这个建议,但泽西/杰克逊似乎不喜欢它:Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions If a class has @XmlElement property, it cannot have @XmlValue property.
  • 请注意,我删除了我看到的与 @XmlElement 相关的所有引用,但仍然出现该错误。
【解决方案2】:

当使用 JAXB 映射 JPA 实体时,我建议使用默认访问(或 XmlAccessType.PROPERTY)并注释 get 方法。 JPA impls 有一些技巧来处理诸如延迟加载之类的事情,在使用字段访问时有时会导致问题。

【讨论】:

    【解决方案3】:

    我无法确定唯一的答案,但它们共同给了我开始检查我的 SQL 结构的想法。事实证明,我的UserRoleList 类采用int 的数据类型。在栅栏的另一边,我的ResultListBigDecimal 数据类型的列表。

    为了消除所有歧义,我修改了我的 SQL 语句以将值作为 VARCHAR 返回,这将作为 String 数据类型对象接收。我更新了我的 UserRoleList 类以表示 String 对象,现在一切正常。

    我将重新审视我的代码以反映数据类型的正确绑定,但现在,这让我克服了困难,因此我可以完成我的解决方案的原型设计。非常感谢所有人,尤其是 DMoses,感谢他们为我们提供了一次快速而富有成效的头脑风暴会议。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-29
      • 2011-01-06
      • 1970-01-01
      • 2015-07-13
      • 2018-12-01
      • 1970-01-01
      • 2021-09-10
      相关资源
      最近更新 更多