首页 文章

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

提问于
浏览
2

关于JAXB封送,我有几个简单的问题 . 我正在尝试封送包含以下字段的类:

@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;

并使用以下序列化代码:

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();
}

我得到的输出是:

<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>

现在,我面临的问题是:

  • 我希望命名空间 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 出现在根元素中,即 TokenRestrictionTemplate 而不是单个子元素 . 我怎样才能做到这一点?

  • 我有一些元素,例如 JAXBElement@XmlElementRef(name = "AlternateVerificationKeys" ...) 但当我编组子元素的名称时,似乎是 ArrayOfTokenVerificationKey 而不是 AlternateVerificationKeys . 我怎样才能解决这个问题?

1 回答

  • 0

    我希望命名空间xmlns:xsi =“http://www.w3.org/2001/XMLSchema-instance”出现在根元素中,即在TokenRestrictionTemplate中,而不是单个子元素 . 我怎样才能做到这一点?

    这是XML的核心功能 . 您可以通过使用抽象类和从第一个继承的多个具体类来实现此目的 . 您还应该使用 @XmlTransient@XmlSeeAlso 来注释抽象类,它们会收到具体类的列表 . 以下是一个例子 .

    1.使用这些注释创建名为 TokenVerificationKey 的抽象类 .

    @XmlTransient
    @XmlSeeAlso({SymmetricVerificationKey.class, X509CertTokenVerificationKey.class})
    public abstract class TokenVerificationKey {
    
    }
    
    1. Finnaly,使用这些注释定义具体类:
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "SymmetricVerificationKey")
    public class SymmetricVerificationKey extends TokenVerificationKey {
    
        @XmlElement(name = "KeyValue")
        private byte[] keyValue;
    
    }
    

    我有一些元素,例如带有@XmlElementRef(name =“AlternateVerificationKeys”...)的JAXBElement但是当我封送子元素的名称时,似乎是ArrayOfTokenVerificationKey而不是AlternateVerificationKeys . 我怎样才能解决这个问题?

    您应该使用 @XmlElementWrapper 使用 @XmlElementWrapper 来创建集合(包装器)元素,并使用 @XmlElement 来设置子元素名称:

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

    此设置与前一个设置相结合,输出如下 .

    使用此技术,您将获得此输出:

    <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>
    

    有条件的信息:

    您可能希望在XML的开头定义命名空间一次 . 您应该定义 "com.sun.xml.bind.namespacePrefixMapper" 属性 . 您还可以为命名空间设置首选前缀 .

    btw:Azure SDK for .NET,使用“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;
            }
        });
    

相关问题