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