Разобрать фрагмент XML, хранящийся в строке, в узлы в XSLT с помощью SAXON для Java
В моем XSLT у меня есть переменная, которая содержит строку. Эта строка содержит фрагмент XML. Это происходит программно, но это эквивалент этого:
<xsl:variable name="xmlfrag" select="'<foo>this <bar>is</bar> it</foo>'"/>
Есть ли способ проанализировать этот XML и добавить его в вывод? Мы используем SAXON для Java.
2 ответа
Решение
Для решения Dimitre требуется лицензионная версия Saxon.
Вот еще одно решение, которое работает также с бесплатной версией Saxon.
Я успешно попробовал с Saxon HE 9.5.X.
Обратный процесс задокументирован здесь.
Речь идет о регистрации пользовательской функции расширения с этим содержанием:
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);
}
}
};
}
}
Вы можете использовать эту функцию следующим образом:
<xs:value-of xmlns:vis="my.custom.uri" select="vis:parse-xml('<a>Test</a>')"/>