Передача файла XML (InputStream) в XSLT позволяет избежать использования документа в XSLT javax.xml

Я новичок в XML, XSLT и javax.xml.

В настоящее время моя цель состоит в том, чтобы объединить два файла XML с помощью XSLT версии 1.0, и все работает нормально.

Но я чувствую, что в моем коде есть ограничение, и я хотел бы избавиться от него, если это возможно.

Это мои ресурсы: 'file1.xml' 'file2.xml' 'merge.xslt'

Это мой метод слияния:

public ByteArrayOutputStream merge(final InputStream file1) {
    final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    final TransformerFactory tFactory = TransformerFactory.newInstance();
    Transformer transformer;
    try {
        transformer = tFactory.newTransformer(new StreamSource("merge.xslt"));
        transformer.transform(new StreamSource(file1), new StreamResult(outputStream));
    } catch (final TransformerConfigurationException e) {
        LOG.warn("Problem occurred transforming files configuration issue", e);
    } catch (final TransformerException e) {
        LOG.warn("Problem occurred transforming files", e);
    }
    return outputStream;
}

Вот как я передаю файл2.xml внутри XSLT

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:param name="lookup" select="document('/file2.xml')"/>

<xsl:template match="/">
  Do the processing how I want
</xsl:template>
</xsl:stylesheet>

Чего я хочу добиться, так это того, что я хотел бы изменить свой метод слияния, чтобы передать файлы file1.xml и file2.xml.

public ByteArrayOutputStream merge(final InputStream file1,final InputStream file2)

И я хочу как-то передать этот файл InputStream2 в XSLT, чтобы снять ограничение на чтение файла из файловой системы.

Может ли кто-нибудь помочь мне, если это возможно и как этого достичь, я был бы очень признателен за всю помощь.

Спасибо.

Я попробовал небольшой пример, упомянутый здесь XSLT Processing with Java: xml в параметре Но у меня это не сработало.

final InputStream file1 = new FileInputStream("file1.xml");
    final InputStream file2 = new FileInputStream("file2.xml");
    final TransformerFactory tFactory = TransformerFactory.newInstance();
    Transformer transformer;
    transformer = tFactory.newTransformer(new StreamSource("merge.xslt"));
    transformer.setParameter("lookup", new StreamSource(file2));
    transformer.transform(new StreamSource(file1), new StreamResult(new FileOutputStream("test.xml")));

И обновил XSLT следующим образом:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:param name="lookup"/>

<xsl:template match="/">
  Do the processing how I want
</xsl:template>
</xsl:stylesheet>

Ошибка, которую я получаю, выглядит следующим образом:

ERROR:  'Invalid conversion from 'javax.xml.transform.stream.StreamSource' to 'node-set'.'
Exception in thread "main" javax.xml.transform.TransformerException: java.lang.RuntimeException: Invalid conversion from 'javax.xml.transform.stream.StreamSource' to 'node-set'.
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:755)
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:359)

Также используя:

<xsl:param name="lookup"/>

Получу ли я доступ к файлу file2.xml внутри XSLT.


person Aniks    schedule 01.10.2014    source источник
comment
При использовании XSLT у вас может быть только один входной документ, кроме документов, которые вы читаете с помощью document(). Вы можете передать имена файлов в команду документа. Или, в качестве альтернативы, вы можете проанализировать документы с помощью синтаксического анализатора DOM и импортировать каждый документ в ваш главный выходной документ, используя функцию importNode.   -  person terrywb    schedule 02.10.2014
comment
@terrywb Я новичок во всем этом, поэтому я на самом деле запутался и не понимаю, что вы пытаетесь направить. На самом деле я хочу избежать использования Document для чтения file2.xml внутри xslt. Хочу, чтобы я передал этот файл2.xml в качестве параметра XSLT в моем java-коде и прочитал его, чтобы сравнить мою логику обработки для слияния. Моя реализация в настоящее время работает. Но я хочу избежать чтения из файловой системы и сохранить этот файл в некотором InputStream. И я не знаю, как передать это в java и прочитать эту информацию внутри XSLT?   -  person Aniks    schedule 02.10.2014
comment
Я не верю, что в XSLT можно делать то, что вы хотите, без использования функции document(). См. мое решение ниже для объединения входных документов с помощью кода.   -  person terrywb    schedule 02.10.2014
comment
Что вам, вероятно, нужно, так это определить Java UriResolver. Когда он определен, он будет служить триггером, вызываемым всякий раз, когда системе необходимо разрешить ссылку document(). В этот момент вы можете просто передать любой входной поток, в который включен ваш документ.   -  person Marcus Rickert    schedule 02.10.2014
comment
@MarcusRickert Можете ли вы показать мне пример кода того, чем вы руководите, я на самом деле не понимаю в деталях, где вы пытаетесь направить меня, спасибо.   -  person Aniks    schedule 02.10.2014
comment
Вы должны посмотреть на docs.oracle.com /javase/7/docs/api/javax/xml/transform/ и docs.oracle.com/javase/7/docs/api/javax/xml/transform/. Насколько я могу это проанализировать (работая с мобильного телефона), классы StreamInput реализуют интерфейс Source. Поэтому, если у вас есть XML-документ, который нужно включить в поток, вы просто передаете этот экземпляр класса потока обратно в UriResolver, который вы зарегистрировали в своем классе обработки XSLT.   -  person Marcus Rickert    schedule 02.10.2014


Ответы (2)


Проведя много исследований и прочитав разные сообщения и блоги, я наконец смог решить свою проблему.

Я передал вопросы, заданные здесь, и у меня появилась идея сделать это.

Передать документ в качестве параметра для перевода XSL в Java

Другие решения, предложенные в этой теме, мне не подошли.

Вот что я сделал,

Использовал URIResolver вместо параметра.

public class DocumentURIResolver implements URIResolver {

final Map<String, Document> _documents;

public DocumentURIResolver(final Map<String, Document> documents) {
    _documents = documents;
}

public Source resolve(final String href, final String base) {
    final Document doc = _documents.get(href);
    return (doc != null) ? new DOMSource(doc) : null;
    }
}

Вот как я изменил свой метод:

public ByteArrayOutputStream merge(final InputStream file1,final InputStream file2) {
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
final TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer;
try {
    transformer = tFactory.newTransformer(new StreamSource("merge.xslt"));
    final DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    final Document documentFile = db.parse(file2);
    Map<String, Document> docs = new HashMap<String, Document>();
    docs.put("lookup", documentFile);
    transformer.setURIResolver(new DocURIResolver(docs));
    transformer.transform(new StreamSource(file1), new StreamResult(outputStream));
} catch (final TransformerConfigurationException e) {
    LOG.warn("Problem occurred transforming files configuration issue", e);
} catch (final TransformerException e) {
    LOG.warn("Problem occurred transforming files", e);
}
return outputStream;
}

И вот как я обозначил это в своем XSLT:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:variable name="lookup" select="document('documentFile')"/>

<xsl:template match="/">
  Do the processing how you want to
</xsl:template>
</xsl:stylesheet>
person Aniks    schedule 03.10.2014

Поскольку вы не хотите использовать функцию document() в своем XSLT, вы можете объединить свои входные файлы, используя функции DOM в Java.

DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document merge = db.newDocument();
Element root = merge.createElement("root");
merge.appendChild(root);
Document d1 = db.parse(new File("file1.xml"));
Document d2 = db.parse(new File("file2.xml"));
root.appendChild(merge.importNode(d1.getDocumentElement(), true));
root.appendChild(merge.importNode(d2.getDocumentElement(), true));

Затем объединенный документ может быть передан в XSLT, если это необходимо.

person terrywb    schedule 01.10.2014
comment
Ну, я понимаю, что вы пытаетесь направить меня. Но я не хочу объединять два документа и фильтровать их с помощью XSLT. Я также отредактировал вопрос, так как пытался проверить функциональность в поисках решений в Интернете. Я думаю, что это возможно, но я не знаю, как это сделать. Ошибка, которую я получаю, я добавил ее к вопросу. - person Aniks; 02.10.2014
comment
У вас есть опыт в этом? Если вы увидите мое редактирование вопроса, возможно, это поможет. Я также связал другой вопрос. - person Aniks; 02.10.2014
comment
@terrywd Я опубликовал решение, я смог его решить. - person Aniks; 03.10.2014