Java 11中的NodeList.getLength()返回0 [英] NodeList.getLength() returning 0 in Java 11

查看:110
本文介绍了Java 11中的NodeList.getLength()返回0的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将应用程序从Java 8迁移到Java11.在Java 8中,我的输入xml文件已正确解析,但是在Java 11中,nodeList.getLength()返回了0.
请根据我总是会收到错误的代码进行引用:Cannot find signature.

I am migrating my application from Java 8 to Java 11. In Java 8, my input xml file was parsing correctly, but in Java 11 the nodeList.getLength() is returning 0.
Please refer the code as per which I am always getting the error: Cannot find signature.

我尝试使用document.getElementsByTagName("Signature")而不是getElementsByTagNameNS(),这将返回正确的length.但是,unmarshalXMLSignature()方法然后给出一个错误,指出Document实现必须支持DOM Level 2并且必须了解名称空间.
在Java 11中使用getElementsByTagNameNS()方法有什么挑战吗?

I have tried using document.getElementsByTagName("Signature") instead of getElementsByTagNameNS(), which returns correct length. However the unmarshalXMLSignature() method then gives an error that Document implementation must support DOM Level 2 and be namespace aware.
Is there any challenge with using getElementsByTagNameNS() method in Java 11?

private DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
. . .
document = documentBuilderFactory.newDocumentBuilder().parse(input);
final NodeList nodeList = document.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
if (nodeList.getLength() == 0) {
    throw new SecurityException("Cannot find signature");
}
final XMLValidateContext validateContext = new DOMValidateContext(newX509KeySelector(), nodeList.item(0));
final XMLSignature signature = getXMLSignatureFactory().unmarshalXMLSignature(validateContext);
. . .

输入的xml是

    <?xml version="1.0" encoding="UTF-8" standalone="no"?><License>
        <id>999</id>
        <companyName>TRXX</companyName>
        <creationDate>01-01-2016</creationDate>
        <expirationDate>never</expirationDate>
        <features>
            <feature>
                <name>drwwy</name>
                <value>true</value>
                <description>drwwy module</description>
            </feature>
            <feature>
                <name>pnp</name>
                <value>true</value>
                <description>Index Number Management module</description>
            </feature>
        </features>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><Reference URI="">
<Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><DigestValue>l5Cl4E=</DigestValue></Reference></SignedInfo><SignatureValue>R3zBkE=</SignatureValue>
<KeyInfo><X509Data><X509SubjectName>CN=TRXX Inc,OU=Product Development,O=TRXX Inc,L=Scotle,ST=Atlanta,C=US</X509SubjectName><X509Certificate>MIY</X509Certificate>
</X509Data></KeyInfo></Signature></License>

我发现,较早时,我注入了JDK的一部分DocumentBuilderFactory,但是Java 11中不再允许它.这就是为什么我使用DocumentBuilderFactory.newInstance()实例化它的原因,但是使用这个作为我的节点列表长度为零.我们可以使用任何其他方式实例化DocumentBuilderFactory对象吗?

Edit 2: I figured out, earlier I was injecting DocumentBuilderFactory which is part of JDK , but it is no longer allowed in Java 11. That is why I instantiated it using DocumentBuilderFactory.newInstance(), but with this one my nodelist length comes as zero. Can we use any other way to instantiate DocumentBuilderFactory object ?

推荐答案

如果使用document.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");,则会得到一个空的nodeList,并且提供的源代码将引发您的new SecurityException("Cannot find signature").

If you use document.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature"); you get an empty nodeList and the source code provided throws your new SecurityException("Cannot find signature").

如果您document.getElementsByTagName("Signature"),则找到了Signature元素,但没有名称空间意识,稍后会抛出此异常:

If you document.getElementsByTagName("Signature"), the Signature element is found but without namespace awareness, throwing this exception later on:

javax.xml.crypto.MarshalException: Document implementation must support DOM Level 2 and be namespace aware
  at org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory.unmarshal(DOMXMLSignatureFactory.java:189)
  at org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory.unmarshalXMLSignature(DOMXMLSignatureFactory.java:150)

在研究术语getElementsByTagNameNS(XMLSignature.XMLNS, "Signature")时,我找到了一些代码示例,在这些代码示例中,它们在DocumentBuilderFactory的新实例上手动激活了名称空间感知:

When researching the term getElementsByTagNameNS(XMLSignature.XMLNS, "Signature") I found code examples where they activate namespace awareness on the new instance of DocumentBuilderFactory manually:

DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);

这应该可以解决您的new SecurityException("Cannot find signature")问题.

This should fix your new SecurityException("Cannot find signature") issue.

关于您先前的问题,您不仅将Java 8迁移到了11,但是还有CDI API,OpenWebBeans,Apache Tomcat以及其他模块,其他人以前必须已经为您完成了命名空间感知的激活. 或者说不同的话-您@Injected注入​​了一个名称空间感知的DocumentBuilderFactory实例.

Regarding your previous question you not only migrated Java 8 to 11, but also CDI API, OpenWebBeans, Apache Tomcat and maybe other modules too, someone else must have done this activation of namespace awareness for you previously. Or saying it differently - you @Injected a namespace aware DocumentBuilderFactory instance.

对于DocumentBuilderFactory的手动配置和注入,请创建一种方法,该方法@Produces DocumentBuilderFactory的实例并将该实例提供给其他地方进行注入:

For manual configuration and injection of DocumentBuilderFactory, create a method that @Produces an instance of the DocumentBuilderFactory and provides that instance for injection elsewhere:

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Produces;
import javax.xml.parsers.DocumentBuilderFactory;

@Dependent
public class DocumentBuilderFactoryProducer {
    @Produces
    @ApplicationScoped
    public DocumentBuilderFactory createDocumentBuilderFactory() {
        DocumentBuilderFactory result = DocumentBuilderFactory.newInstance();
        result.setNamespaceAware(true);
        // other customizations ...
        return result;
    }
}

这可以像这样注入到其他bean中:

This can be injected into other beans like so:

@Inject
private DocumentBuilderFactory documentBuilderFactory;

这篇关于Java 11中的NodeList.getLength()返回0的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆