简体   繁体   English

JAXB编组-根元素和元素Ref名称问题的命名空间

[英]JAXB Marshalling - Namespace for root element & element Ref name issue

I have couple simple questions regarding JAXB marshaling. 关于JAXB封送处理,我有几个简单的问题。 I am trying to marshal a class containing the following fields: 我试图封送一个包含以下字段的类:

@XmlElementRef(name = "AlternateVerificationKeys", namespace = "http://schemas.microsoft.com/Azure/MediaServices/KeyDelivery/TokenRestrictionTemplate/v1", type = JAXBElement.class, required = false)
protected JAXBElement<ArrayOfTokenVerificationKey> alternateVerificationKeys;

@XmlElement(name = "Audience", required = true, nillable = true)
@XmlSchemaType(name = "anyURI")
protected String audience;

@XmlElement(name = "Issuer", required = true, nillable = true)
@XmlSchemaType(name = "anyURI")
protected String issuer;

@XmlElement(name = "PrimaryVerificationKey", required = true, nillable = true)
protected TokenVerificationKey primaryVerificationKey;

@XmlElementRef(name = "RequiredClaims", namespace = "http://schemas.microsoft.com/Azure/MediaServices/KeyDelivery/TokenRestrictionTemplate/v1", type = JAXBElement.class, required = false)
protected JAXBElement<ArrayOfTokenClaim> requiredClaims;

@XmlElement(name = "TokenType", required = true)
@XmlSchemaType(name = "string")
protected TokenType tokenType;

And using simply the following serialization code: 并仅使用以下序列化代码:

public static String asString(JAXBContext pContext, Object pObject) throws JAXBException {
    StringWriter sw = new StringWriter();

    Marshaller marshaller = pContext.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
    marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
    marshaller.marshal(pObject, sw);

    return sw.toString();
}

The output I get is: 我得到的输出是:

<TokenRestrictionTemplate xmlns="http://schemas.microsoft.com/Azure/MediaServices/KeyDelivery/TokenRestrictionTemplate/v1">
    <ArrayOfTokenVerificationKey>
        <TokenVerificationKey
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="SymmetricVerificationKey">
            <KeyValue></KeyValue>
        </TokenVerificationKey>
    </ArrayOfTokenVerificationKey>
    <Audience>urn:test</Audience>
    <Issuer>http://testacs.com/</Issuer>
    <PrimaryVerificationKey
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="SymmetricVerificationKey">
        <KeyValue></KeyValue>
    </PrimaryVerificationKey>
    <ArrayOfTokenClaim>
        <TokenClaim>
            <ClaimType>urn:microsoft:azure:mediaservices:contentkeyidentifier</ClaimType>
            <ClaimValue
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
        </TokenClaim>
    </ArrayOfTokenClaim>
    <TokenType>SWT</TokenType>
</TokenRestrictionTemplate>

Now, here are the problems I am facing: 现在,这是我面临的问题:

  1. I want the namespace xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" to appear in the root element ie in TokenRestrictionTemplate instead of individual child elements. 我希望名称空间xmlns:xsi =“ http://www.w3.org/2001/XMLSchema-instance”出现在根元素中,即TokenRestrictionTemplate中,而不是单个子元素中。 How can I achieve that? 我该如何实现?

  2. I have some elements eg JAXBElement with @XmlElementRef(name = "AlternateVerificationKeys" ...) but when I marshal the name of the child element appears to be ArrayOfTokenVerificationKey rather than AlternateVerificationKeys . 我有一些元素,例如带有@XmlElementRef(name =“ AlternateVerificationKeys” ...)的 JAXBElement ,但是当我编组时,子元素的名称似乎是ArrayOfTokenVerificationKey而不是AlternateVerificationKeys How can I fix this? 我怎样才能解决这个问题?

I want the namespace xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" to appear in the root element ie in TokenRestrictionTemplate instead of individual child elements. 我希望名称空间xmlns:xsi =“ http://www.w3.org/2001/XMLSchema-instance”出现在根元素中,即TokenRestrictionTemplate中,而不是单个子元素中。 How can I achieve that? 我该如何实现?

That is a core feature of XML. 这是XML的核心功能。 You can achieve this by using an abstract class and multiple concrete classes inherited from first one. 您可以通过使用抽象类和从第一个继承的多个具体类来实现此目的。 Also you should annotate the abstract class with @XmlTransient and @XmlSeeAlso who receive a list of concrete classes. 另外,您应该使用@XmlTransient@XmlSeeAlso注释抽象类, @XmlTransient会收到具体类的列表。 An example below. 下面的例子。

1. Create an abstract class named TokenVerificationKey , with these annotations. 1.使用这些注释创建一个名为TokenVerificationKey的抽象类。

@XmlTransient
@XmlSeeAlso({SymmetricVerificationKey.class, X509CertTokenVerificationKey.class})
public abstract class TokenVerificationKey {

}

2. Finnaly, define the concrete classes with these annotations: 2.最后,使用以下注释定义具体的类:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "SymmetricVerificationKey")
public class SymmetricVerificationKey extends TokenVerificationKey {

    @XmlElement(name = "KeyValue")
    private byte[] keyValue;

}

I have some elements eg JAXBElement with @XmlElementRef(name = "AlternateVerificationKeys" ...) but when I marshal the name of the child element appears to be ArrayOfTokenVerificationKey rather than AlternateVerificationKeys. 我有一些元素,例如带有@XmlElementRef(name =“ AlternateVerificationKeys” ...)的JAXBElement,但是当我编组时,子元素的名称似乎是ArrayOfTokenVerificationKey而不是AlternateVerificationKeys。 How can I fix this? 我怎样才能解决这个问题?

You should annotate TokenRestrictionTemplate.alternateVerificationKeys using @XmlElementWrapper to create the collection (a wrapper) element and @XmlElement to set the childs element name: 您应该使用@XmlElementWrapper注释TokenRestrictionTemplate.alternateVerificationKeys来创建集合(包装)元素,并使用@XmlElement设置子元素的名称:

@XmlElementWrapper(name = "AlternateVerificationKeys")
@XmlElement(name = "TokenVerificationKey")
private List<TokenVerificationKey> alternateVerificationKeys;

This setup combined with the previous one, makes an output as below. 该设置与上一个设置结合在一起,输出如下。

With this technique you will get this output: 使用此技术,您将获得以下输出:

<TokenRestrictionTemplate xmlns="http://schemas.microsoft.com/Azure/MediaServices/KeyDelivery/TokenRestrictionTemplate/v1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <AlternateVerificationKeys>
        <TokenVerificationKey i:type="SymmetricVerificationKey">
            <KeyValue>cGVwZXBlZGtkZGllZGpkamRqZGplaWRqZWVpZGplaWRqaWpkZWltZGVpbWRlaWRpZWQ=</KeyValue>
        </TokenVerificationKey>
        <TokenVerificationKey i:type="X509CertTokenVerificationKey">
            <RawBody>MIIDqDCCAxGgAwIBAgIJAMAU1MJasjgBMA0GCSqGSIb3DQEBBQUAMIGVMQswCQYDVQQGEwJBUjENMAsGA1UECBMEQlNBUzENMAsGA1UEBxMEQ0FCQTEXMBUGA1UEChMOU291dGh3b3JrcyBTUkwxGTAXBgNVBAsTEERldmVsb3BtZW50IFVuaXQxCzAJBgNVBAMTAkVWMScwJQYJKoZIhvcNAQkBFhh2ZWNjaGlvZW1hbnVlbEBnbWFpbC5jb20wHhcNMTUwNzE0MTc1MjQ0WhcNMTgwNDEwMTc1MjQ0WjCBlTELMAkGA1UEBhMCQVIxDTALBgNVBAgTBEJTQVMxDTALBgNVBAcTBENBQkExFzAVBgNVBAoTDlNvdXRod29ya3MgU1JMMRkwFwYDVQQLExBEZXZlbG9wbWVudCBVbml0MQswCQYDVQQDEwJFVjEnMCUGCSqGSIb3DQEJARYYdmVjY2hpb2VtYW51ZWxAZ21haWwuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJC2kNjNnBw2hyyI3Hbu30PRXw17GGfHytyvgB89nuakoFE2Oe7Ic8NDPN5/WeA7MROH7dDKole+MFOjDeSO/8d7ylWieVu08/yVpJwcgM3hV7X9Jbc5Zl0XsMXUxXaLvYAaLb3Kc8LrPPBJtTI2bXesV7AGxYKqcDIpwfQ7BGHwIDAQABo4H9MIH6MB0GA1UdDgQWBBTKcw3CsHdNrjqsOPKCoD+59Nh9ijCBygYDVR0jBIHCMIG/gBTKcw3CsHdNrjqsOPKCoD+59Nh9iqGBm6SBmDCBlTELMAkGA1UEBhMCQVIxDTALBgNVBAgTBEJTQVMxDTALBgNVBAcTBENBQkExFzAVBgNVBAoTDlNvdXRod29ya3MgU1JMMRkwFwYDVQQLExBEZXZlbG9wbWVudCBVbml0MQswCQYDVQQDEwJFVjEnMCUGCSqGSIb3DQEJARYYdmVjY2hpb2VtYW51ZWxAZ21haWwuY29tggkAwBTUwlqyOAEwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBVuuFO3cyOPKSE1nvNyshAeRqhRD+igICeCHGP2zpFQ05k4lzRoio/+1/zdkwZ7g1jHSXz+QkGPRjAxMKGoK8huiTvJwJ1jDVNqyJqfnCW4S2AoNCwziKgGriL7luSDZ+PG3MxoNaCB63B6M6OKOezXhFk4VeLJ/NY1Eohe9E1ew==</RawBody>
        </TokenVerificationKey>
    </AlternateVerificationKeys>
    <Audience>http://audience.com</Audience>
    <Issuer>https://issuer.com</Issuer>
    <PrimaryVerificationKey i:type="SymmetricVerificationKey">
        <KeyValue>cGVwZXBlZGtkZGllZGpkamRqZGplaWRqZWVpZGplaWRqaWpkZWltZGVpbWRlaWRpZWQ=</KeyValue>
    </PrimaryVerificationKey>
    <RequiredClaims>
        <TokenClaim>
            <ClaimType>urn:microsoft:azure:mediaservices:contentkeyidentifier</ClaimType>
            <ClaimValue i:nil="true"/>
        </TokenClaim>
    </RequiredClaims>
    <TokenType>SWT</TokenType>
</TokenRestrictionTemplate> 

Aditional Info: 附加信息:

You could want define the namespace once at the beginning of the XML. 您可能希望在XML的开头定义一次名称空间。 You should define the "com.sun.xml.bind.namespacePrefixMapper" propery. 您应该定义"com.sun.xml.bind.namespacePrefixMapper"属性。 You can also set the preferred prefix for the namespace. 您还可以设置名称空间的首选前缀。

btw: Azure SDK for .NET, uses "i" as prefix. 顺便说一句:用于.NET的Azure SDK,使用“ i”作为前缀。

    Marshaller m = context.createMarshaller();
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    m.setProperty("com.sun.xml.bind.namespacePrefixMapper", new    NamespacePrefixMapper() {
        @Override
        public String[] getPreDeclaredNamespaceUris() {
            return new String[] {
                    // "http://www.w3.org/2001/XMLSchema-instance"
                    XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI
                    };
        }

        @Override
        public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
            // "http://www.w3.org/2001/XMLSchema-instance"
            if (namespaceUri.equals(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI)) {
                return "i";
            }
            return suggestion;
        }
    });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM