Como adiciono um atributo de espaço para nome a um elemento no JAXB ao marcar?
-
20-09-2019 - |
Pergunta
Estou trabalhando com o LMS (grandes serviços comerciais) do eBay e continuei correndo no erro:
org.xml.sax.saxException:
Simpledseserializer encontrou uma criança
elemento, o que não é esperado, em
algo que estava tentando
Desserialize.
Depois muito de tentativa e erro, rastreei o problema. Acontece que isso funciona:
<?xml version="1.0" encoding="UTF-8"?>
<BulkDataExchangeRequests xmlns="urn:ebay:apis:eBLBaseComponents">
<Header>
<Version>583</Version>
<SiteID>0</SiteID>
</Header>
<AddFixedPriceItemRequest xmlns="urn:ebay:apis:eBLBaseComponents">
Enquanto isso (o que tenho enviado) não:
<?xml version="1.0" encoding="UTF-8"?>
<BulkDataExchangeRequests xmlns="urn:ebay:apis:eBLBaseComponents">
<Header>
<Version>583</Version>
<SiteID>0</SiteID>
</Header>
<AddFixedPriceItemRequest>
A diferença é o atributo xml namespace no AddFixedPriceItemRequest
. Atualmente, todo o meu XML está sendo marcado via Jaxb e não tenho certeza de qual é a melhor maneira de adicionar um segundo atributo xmlns a um elemento diferente no meu arquivo.
Então essa é a pergunta. Como adicionar um atributo xmlns a outro elemento no JAXB?
package ebay.apis.eblbasecomponents;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "AddFixedPriceItemRequestType", propOrder = {
"item"
})
public class AddFixedPriceItemRequestType
extends AbstractRequestType
{
@XmlElement(name = "Item")
protected ItemType item;
public ItemType getItem() {
return item;
}
public void setItem(ItemType value) {
this.item = value;
}
}
Definição de classe adicionada por solicitação.
Editou a classe acima como sem efeito:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(namespace = "urn:ebay:apis:eBLBaseComponents",
name = "AddFixedPriceItemRequestType", propOrder = {
"item"
})
public class AddFixedPriceItemRequestType
Aqui está um trecho do BulkDataExchangeRequestsType
classe. Eu tentei jogar um namespace="urn:ebay:apis:eBLBaseComponents"
no @XmlElement
por AddFixedPriceItemRequest
Mas não fez nada.
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "BulkDataExchangeRequestsType", propOrder = {
"header",
"addFixedPriceItemRequest"
})
public class BulkDataExchangeRequestsType {
@XmlElement(name = "Header")
protected MerchantDataRequestHeaderType header;
@XmlElement(name = "AddFixedPriceItemRequest")
protected List<AddFixedPriceItemRequestType> addFixedPriceItemRequest;
Solução
Até onde eu sei, seus fragmentos XML são semanticamente idênticos. o xmlns
atributo no AddFixedPriceItemRequest
O elemento é redundante, pois herda implicitamente o espaço para nome do seu elemento pai. Jaxb sabe disso e, portanto, não se incomoda em adicionar o espaço para nome a AddFixedPriceItemRequest
- simplesmente não é necessário.
Se o servidor do eBay estiver funcionando apenas quando o AddFixedPriceItemRequest
xmlns
está presente, então está quebrado e está fazendo demandas sobre a entrada acima das exigidas pelo XML e pelo esquema. Se esse é realmente o caso (o que é difícil de acreditar, mas possível), o uso de um modelo de documento Java XML como o JAXB será uma luta, pois isso assumirá que o XML é XML é XML. Peidando de baixo nível sobre quais elementos obtêm o xmlns
As declarações não são expostas à API, pois não deve ser necessária.
Nenhum dos quais está ajudando você. Minha abordagem seria marcar o modelo Jaxb para um objeto DOM (usando um DOMResult
passou para o Marshaller
), e então veja se você pode fazer alguns ajustes manuais do DOM para forçar o xmlns
no documento nos lugares apropriados. Você pode então serializar esse DOM para XML e enviar isso.
Você não deveria ter que fazer isso, e eu suspeito que você esteja fazendo algo mais errado em algum lugar; Isso é mais provável do que o serviço da Web do eBay sendo quebrado assim.
EDIT: Aqui está outra sugestão, um pouco menos horrível que a solução Jaxb-to-Dom-para-XML. Se a sua solicitação XML for uma estrutura estática razoável, com apenas os valores numéricos/strings alterando, defina -o como um modelo de string, substitua os valores em tempo de execução e envie isso. Você pode interpretar os resultados usando o JAXB. Eu fiz isso no OAST com os serviços da Web que exigiu prefixos exatos de namespace, ao convencer as bibliotecas Java XML a se conformar com isso irracionalmente.
Outras dicas
Tente usar a anotação de classe
@XmlType(namespace="urn:ebay:apis:eBLBaseComponents")
ou
@XmlElement(namespace="urn:ebay:apis:eBLBaseComponents")
Anotação de propriedades se você deseja especificar apenas namespace em alguns casos
Verifique se os campos em uma classe gerada estão faltando o @XmlElement
anotação e, se presente, eles estão perdendo o atributo do espaço para nome. Esses dois devem estar presentes para obter o prefixo do espaço para o nome de todos os elementos do seu XML marechal.