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

JAXB编组-根元素的命名空间

薛望
2023-03-14

我有几个关于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中,而不是单个子元素中。如何实现这一点?

    我有一些元素,例如带有@XmlElementRef(name="AlternateVerficationKeys"...)的JAXBElement,但是当我列表时,子元素的名称似乎是ArrayOfTokenVerficationKey而不是AlternateVerficationKeys。我如何解决这个问题?

  • 共有1个答案

    郭胤
    2023-03-14

    我想要名称空间xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance“出现在根元素中,即TokenRestrictionTemplate中,而不是单个子元素中。如何实现这一点?

    这是XML的核心特性。您可以通过使用一个抽象类和从第一个继承的多个具体类来实现这一点。您还应该使用@Xml瞬态@XmlSeeAnd来注释抽象类,他们会收到具体类的列表。下面的示例。

    1、使用这些注释创建一个名为TokenVerificationKey的抽象类。

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

    2、最后,用这些注释定义具体类:

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "SymmetricVerificationKey")
    public class SymmetricVerificationKey extends TokenVerificationKey {
    
        @XmlElement(name = "KeyValue")
        private byte[] keyValue;
    
    }
    

    我有一些元素,例如带有@XmlElementRef(name="AlternateVerficationKeys"...)的JAXBElement,但是当我列表时,子元素的名称似乎是ArrayOfTokenVerficationKey而不是AlternateVerficationKeys。我如何解决这个问题?

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

    @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.namespacePrefix Mapper"属性。您还可以为命名空间设置首选前缀。

    顺便说一句:的Azure SDK。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;
            }
        });
    
     类似资料:
    • 使用JAXB编组时,我是否会影响将声明命名空间/命名空间前缀的元素? 目前,所有名称空间前缀都在根元素处声明,但由于处理XML的系统的奇怪限制,我需要在子元素处声明它们(这仍然会导致有效的XML文档)。 在2006年,一位开发人员曾向官方jaxb问题跟踪器提出过一个类似但不完全相同的请求,但拒绝了。我想知道这一情况是否同时发生了变化,或者是否存在一些解决方法。 任何帮助是值得赞赏的。 例子: JA

    • 这是我的xml,需要把它转换成Java。我使用了jaxb 并抛出以下异常javax.xml.bind.unmarshalException:意外元素(URI:“http://www.ae.com/event/load”,local:“order”)。需要的元素为<{}LM:order>

    • 我的代码如下: 我怎样才能让它工作?如果我的xml标记有一些相关元素,如上面的“xmlns”,则JAXB解组器会抛出异常。 这是我第一次这么做,所以我对JAXB、解编等都一无所知。我在苦苦挣扎任何帮助都是好的。 编辑StackTrace:

    • 是否有一种使用JAXB从非根元素以编程方式获取名称空间的方法? 我可以在根元素上使用以下内容(其中DetailedReport是根元素对象): 但是,如果我尝试使用来自同一个包的类型,但不是根元素,qname为null。 根据JAXBIntrospector的javadocs: 参数对象是以下情况的JAXB元素: 它是javax.xml.bind.JAXBElement的实例,object的类用@

    • 问题内容: 因此,我试图封送对象的一般列表,但我希望每个列表都具有特定的XmlRootElement(name ..)。我这样做的方式,我知道如果没有为每种类型的对象编写特定的包装器类并声明XmlRootElement,这实际上是不可能的。但是也许还有另一种方式…? 考虑以下类别: 如预期的那样,将产生: 我想要的是能够修改标签名称,具体取决于我创建EntityList所使用的实体的类型。 我知道

    • 我需要你在JAXB编组方面的帮助。这是关于命名空间的。我在这个令人惊叹的网站上阅读了不同的博客和很多答案,但我还没有意识到如何解决我的问题。 我需要用一些复杂的(至少对我来说)名称空间生成一个XML。 如您所见,该XML具有 < code > xmlns:xsi = " http://www . w3 . org/2001/XML schema-instance " 和 http://www.sa