Parse an XML fragment stored in a string into nodes in XSLT with SAXON for Java

北城余情 提交于 2019-12-12 20:29:19

问题


In my XSLT, I have a variable which contains a string. This string contains a fragment of XML. This is coming in programmatically, but its the equivalent of this:

<xsl:variable name="xmlfrag" select="'<foo>this <bar>is</bar> it</foo>'"/>

Is there a way to parse this XML and add it to the output? We're using SAXON for Java.


回答1:


Use the saxon:parse() extension function.




回答2:


The Dimitre solution requires a licensed version of Saxon.

Here is another solution that works also with the free version of Saxon.

I've tried it successfully with Saxon HE 9.5.X.

The inverse process is documented here.

It is about registering a custom extension function with these contents:

import net.sf.saxon.expr.XPathContext;
import net.sf.saxon.lib.ExtensionFunctionCall;
import net.sf.saxon.lib.ExtensionFunctionDefinition;
import net.sf.saxon.om.Sequence;
import net.sf.saxon.om.StructuredQName;
import net.sf.saxon.s9api.DocumentBuilder;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.value.SequenceType;

import javax.xml.transform.stream.StreamSource;

import java.io.StringReader;

@SuppressWarnings("serial")
public class XmlParser extends ExtensionFunctionDefinition {
    @Override
    public StructuredQName getFunctionQName() {
        return new StructuredQName("vis", URI, "my.custom.uri");
    }

    @Override
    public SequenceType[] getArgumentTypes() {
        return new SequenceType[] { SequenceType.SINGLE_STRING };
    }

    @Override
    public SequenceType getResultType(SequenceType[] sequenceTypes) {
        return SequenceType.NODE_SEQUENCE;
    }

    @Override
    public ExtensionFunctionCall makeCallExpression() {
        return new ExtensionFunctionCall() {
            DocumentBuilder constructor;

            @Override
            public Sequence call(XPathContext ctx, Sequence[] secs) throws XPathException {
                // Not synchronized, as worst case it initialize twice
                if (constructor == null)
                    constructor = new Processor(ctx.getConfiguration()).newDocumentBuilder();
                String xml = secs[0].head().getStringValue();
                try {
                    return constructor.build(new StreamSource(new StringReader(xml))).getUnderlyingNode();
                } catch (SaxonApiException e) {
                    final int max = 500;
                    String xml2 = xml.length() > 500 ? xml.substring(0, max)+"..." : xml;
                    throw new XPathException("Error when parsing XML.\n"+xml2, e);
                }
            }
        };
    }
}

You can use this function as follows:

<xs:value-of xmlns:vis="my.custom.uri" select="vis:parse-xml('<a>Test</a>')"/>


来源:https://stackoverflow.com/questions/4522640/parse-an-xml-fragment-stored-in-a-string-into-nodes-in-xslt-with-saxon-for-java

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!