我应该如何调试 Nokogiri 空指针异常?

How should I debug a Nokogiri Null Pointer exception?

承包商为我的一个客户创建了一个相当复杂的 XSLT。它适用于各种转换测试工具,使用来自我们应用程序的真实数据。但是 Nokogiri 在变换过程中吐了出来。设置 $VERBOSE 和 $DEBUG 后,我仍然得到信息不足的信息:

Exception `RuntimeError' at nokogiri/XsltStylesheet.java:231 - java.lang.NullPointerException

所以我想我会创建一个带有一些调试代码的自定义 Nokogiri Gem,在我的 Gem 文件中使用它:

gem 'nokogiri', :git => 'ssh://git@192.168.185.65:7999/bssc/nokogiri.git'

由于版本控制问题我不明白如何解决,这不起作用:

Source does not contain any versions of 'nokogiri java'

所以在这一点上,我想我应该伸出援手,向社区征求更好的意见。我确定 Nokogiri 对样式表中的某些内容不满意,但由于 XSLT 的复杂性,很难找到它。

建议?

...已经使用 Nokogiri 完成了一些 Java 原生分机提升(performance/cleanup 在 1.7/1.8 中更新)

这取决于您是否有指向合理位置的跟踪,尝试 jruby -Xbacktrace.style=raw ... 如果这没有揭示有价值的见解,您可能需要自己构建 gem(有它的一个抽成任务只是确保你在 JRuby).

下进行

您不能将 Bundler 与 :git 一起使用,因为 .gemspec 是根据 Ruby 平台生成的,因此您需要手动构建 gem install (调整版本并使用 Bundler 进行设置,这样您就知道您使用的是哪一个)。

祝你好运!

我不确定这是最好的方法,但在我的 RVM 环境中编辑源代码,然后最小化 build_all,允许我删除异常处理。我的修改 XsltStylesheet.java :

    @JRubyMethod
    public IRubyObject serialize(ThreadContext context, IRubyObject doc) throws IOException, TransformerException {
        XmlDocument xmlDoc = (XmlDocument) doc;
        TransformerImpl transformer = (TransformerImpl) this.sheet.newTransformer();
        ByteArrayOutputStream writer = new ByteArrayOutputStream();
        StreamResult streamResult = new StreamResult(writer);
        SerializationHandler serializationHandler = transformer.createSerializationHandler(streamResult);
        serializationHandler.serialize(xmlDoc.getNode());
        return context.getRuntime().newString(writer.toString());
    }

    @JRubyMethod(rest = true, required=1, optional=2)
    public IRubyObject transform(ThreadContext context, IRubyObject[] args) throws TransformerException, IOException {
        Ruby runtime = context.getRuntime();
System.out.println("in transform");
        argumentTypeCheck(runtime, args[0]);
System.out.println("before listener");

        // NokogiriXsltErrorListener elistener = new NokogiriXsltErrorListener();
    System.out.println("before dom");

        DOMSource domSource = new DOMSource(((XmlDocument) args[0]).getDocument());
        final DOMResult result; String stringResult = null;
    System.out.println("try transform");

            result = tryXsltTransformation(context, args, domSource, null); // DOMResult





        if (stringResult == null) {
            return createDocumentFromDomResult(context, runtime, result);
        } else {
            return createDocumentFromString(context, runtime, stringResult);
        }
    }

    private DOMResult tryXsltTransformation(ThreadContext context, IRubyObject[] args, DOMSource domSource, NokogiriXsltErrorListener elistener) throws TransformerException {
        Transformer transf = sheet.newTransformer();
        transf.reset();
        // transf.setErrorListener(elistener);
        if (args.length > 1) {
            addParametersToTransformer(context, transf, args[1]);
        }

        DOMResult result = new DOMResult();
        transf.transform(domSource, result);
        return result;
    }

这是我的全部构建脚本:

#! /usr/bin/env bash
#
#  script to build gems for all relevant platforms:
#  - MRI et al (standard gem)
#  - windows (x86-mingw32 and x64-mingw32)
#  - jruby
#

# Load RVM into a shell session *as a function*
if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then
    source "$HOME/.rvm/scripts/rvm"
elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then
    source "/usr/local/rvm/scripts/rvm"
else
    echo "ERROR: An RVM installation was not found.\n"
fi

set -o errexit

rm -rf tmp pkg
bundle exec rake clean clobber

# holding pen
rm -rf gems
mkdir -p gems

# windows

# MRI

# jruby
bundle exec rake clean clobber
bundle exec rake generate

gem install bundler --conservative
bundle install --quiet --local || bundle install
bundle exec rake gem
cp -v pkg/nokogiri*java.gem gems

这产生了输出:

...
try transform
file:///Users/jeff/Documents/BlueSageSource/plus/dummy.xsl; Line #0; Column #0; org.apache.xpath.objects.XRTreeFrag cannot be cast to org.apache.xpath.objects.XNodeSet
file:///Users/jeff/Documents/BlueSageSource/plus/dummy.xsl; Line #0; Column #0; java.lang.NullPointerException

'cannot be cast' 消息让我找到了其他信息,表明 Nokogiri 不支持 XSLT 2。这令人失望,与其说是因为限制,不如说是因为它没有很好的文档记录,并且失败了空指针异常充其量是不友好的。我认为我们有足够的信息来创建一个最小的失败案例以作为改进请求提交。

参考文献:

Nokogiri does not intend to support XSLT 2

Nokogiri does not support XSLT 2