Объединение двух файлов XML в Java

У меня есть два файла XML с аналогичной структурой, которые я хочу объединить в один файл. В настоящее время я использую EL4J XML Merge, с которым я столкнулся в этом учебнике. Однако он не сливается, так как я ожидаю, что для экземпляров основной проблемой является его не слияние из обоих файлов в один элемент, например один, который содержит 1, 2, 3 и 4. Вместо этого он просто отбрасывает 1 или 2 или 3 и 4 в зависимости от того, какой файл сначала сложен.

Поэтому я был бы благодарен всем, у кого есть опыт работы с XML Merge, если бы они могли сказать мне, что я могу сделать неправильно, или же кто-нибудь знает о хорошем XML API для Java, который мог бы слить файлы по мере необходимости?

Большое спасибо за вашу помощь в продвижении

Редактировать:

Мог бы действительно сделать с некоторыми хорошими предложениями по этому поводу, так что добавил щедрость. Я пробовал предложение jdigital, но все еще имею проблемы с слиянием XML.

Ниже приведен пример структуры XML-файлов, которые я пытаюсь объединить.

                                                    

Ожидаемый результат

                                    

Не очень элегантный, но вы можете сделать это с парсером DOM и XPath:

 public class MergeXmlDemo { public static void main(String[] args) throws Exception { // proper error/exception handling omitted for brevity File file1 = new File("merge1.xml"); File file2 = new File("merge2.xml"); Document doc = merge("/run/host/results", file1, file2); print(doc); } private static Document merge(String expression, File... files) throws Exception { XPathFactory xPathFactory = XPathFactory.newInstance(); XPath xpath = xPathFactory.newXPath(); XPathExpression compiledExpression = xpath .compile(expression); return merge(compiledExpression, files); } private static Document merge(XPathExpression expression, File... files) throws Exception { DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory .newInstance(); docBuilderFactory .setIgnoringElementContentWhitespace(true); DocumentBuilder docBuilder = docBuilderFactory .newDocumentBuilder(); Document base = docBuilder.parse(files[0]); Node results = (Node) expression.evaluate(base, XPathConstants.NODE); if (results == null) { throw new IOException(files[0] + ": expression does not evaluate to node"); } for (int i = 1; i < files.length; i++) { Document merge = docBuilder.parse(files[i]); Node nextResults = (Node) expression.evaluate(merge, XPathConstants.NODE); while (nextResults.hasChildNodes()) { Node kid = nextResults.getFirstChild(); nextResults.removeChild(kid); kid = base.importNode(kid, true); results.appendChild(kid); } } return base; } private static void print(Document doc) throws Exception { TransformerFactory transformerFactory = TransformerFactory .newInstance(); Transformer transformer = transformerFactory .newTransformer(); DOMSource source = new DOMSource(doc); Result result = new StreamResult(System.out); transformer.transform(source, result); } } 

Это предполагает, что вы можете одновременно удерживать как минимум два документа в оперативной памяти.

Я использую XSLT для слияния XML-файлов. Это позволяет мне настроить операцию слияния, чтобы просто соединить контент вместе или объединиться на определенном уровне. Это немного больше работы (и синтаксис XSLT является особым), но супер гибким. Несколько вещей, которые вам нужны здесь

a) Включите дополнительный файл. b) Скопируйте исходный файл 1: 1. c) Создайте свою точку слияния с уклоном дублирования или без него.

a) В начале я

 yoursecondfile.xml  

это позволяет указывать на второй файл, используя $ mDoc

b) Инструкции по копированию исходного дерева 1: 1 – 2 шаблона:

           

Ни с чем другим вы не получаете 1: 1 копию вашего первого исходного файла. Работает с любым типом XML. Объединяющая часть является файловой. Предположим, что у вас есть элементы событий с атрибутом идентификатора события. Вы не хотите дублировать идентификаторы. Шаблон будет выглядеть так:

                   

Конечно, вы можете сравнить другие вещи, такие как имена тегов и т. Д. Также зависит от вас, насколько глубока слияние. Если у вас нет ключа для сравнения, конструкция становится проще, например, для журнала:

        

Для запуска XSLT в Java используйте это:

  Source xmlSource = new StreamSource(xmlFile); Source xsltSource = new StreamSource(xsltFile); Result xmlResult = new StreamResult(resultFile); TransformerFactory transFact = TransformerFactory.newInstance(); Transformer trans = transFact.newTransformer(xsltSource); // Load Parameters if we have any if (ParameterMap != null) { for (Entry curParam : ParameterMap.entrySet()) { trans.setParameter(curParam.getKey(), curParam.getValue()); } } trans.transform(xmlSource, xmlResult); 

или вы загружаете Saxon SAX Parser и делаете это из командной строки (пример оболочки Linux):

 #!/bin/bash notify-send -t 500 -u low -i gtk-dialog-info "Transforming $1 with $2 into $3 ..." # That's actually the only relevant line below java -cp saxon9he.jar net.sf.saxon.Transform -t -s:$1 -xsl:$2 -o:$3 notify-send -t 1000 -u low -i gtk-dialog-info "Extraction into $3 done!" 

YMMV

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

Таким образом, я сделал DTD, связанный с файлами XML, которые я слиял, и из них создавал ряд classов, отражающих структуру. Из этого я использовал XStream для повторной инициализации XML-файла в classах.

Таким образом, я аннотировал мои classы, создавая для него процесс использования комбинации правил, назначенных аннотациями, и некоторого отражения, чтобы объединить объекты, а не объединять фактическую структуру XML.

Если кому-то интересен код, который в этом случае объединяет файлы XML Nmap, см. http://fluxnetworks.co.uk/NmapXMLMerge.tar.gz коды не совершенные, и я признаю, что они не являются гибкими, но это определенно работает. Я планирую переопределить систему, когда он автоматически анализирует DTD, когда у меня есть свободное время.

Вот как это должно выглядеть с помощью XML Merge:

 action.default=MERGE xpath.info=/run/info action.info=PRESERVE xpath.result=/run/host/results/result action.result=MERGE matcher.result=ID 

Вы должны установить идентификатор ID для // результирующего узла и установить действие PRESERVE для // информационного узла. Также будьте осторожны, что .properties Использование XML Merge чувствительно к регистру – вы должны использовать «xpath», а не «XPath» в своих .properties.

Не забудьте указать параметр -config следующим образом:

 java -cp lib\xmlmerge-full.jar; ch.elca.el4j.services.xmlmerge.tool.XmlMergeTool -config xmlmerge.properties example1.xml example2.xml 

Это может помочь, если вы были в явном виде о том, что вы заинтересованы в достижении. Это то, о чем вы просите?

Doc A:

       

Doc B:

    

Слияние результатов:

        

Вы беспокоитесь о масштабировании больших документов?

Самый простой способ реализовать это в Java – использовать streamовый XML-парсер (google для «java StAX»). Если вы используете библиотеку javax.xml.stream, вы обнаружите, что XMLEventWriter имеет удобный метод XMLEventWriter # add (XMLEvent). Все, что вам нужно сделать, – это петля над элементами верхнего уровня в каждом документе и добавить их к вашей записи с помощью этого метода для создания объединенного результата. Единственная фанковая часть – это реализация логики считывателя, которая учитывает (только вызывает «add») на узлах верхнего уровня.

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

Я посмотрел ссылку на ссылку; странно, что XMLMerge не работает должным образом. Ваш пример кажется простым. Вы прочитали раздел « Использование объявлений XPath с помощью XmlMerge ? Используя пример, попробуйте настроить XPath для получения результатов и установить его для слияния. Если я правильно прочитаю документ, это будет выглядеть примерно так:

 XPath.resultsNode=results action.resultsNode=MERGE 

Возможно, вы сможете написать приложение java, которое обезвреживает XML-документы в объекты, а затем «объединить» отдельные объекты программно в коллекцию. Затем вы можете сериализовать объект коллекции обратно в XML-файл со всем, что «слилось».

В JAXB API есть несколько инструментов, которые могут конвертировать XML-документ / схему в classы Java. Инструмент «xjc» мог бы это сделать, хотя я не могу вспомнить, можете ли вы создавать classы непосредственно из документа XML, или если вам нужно сначала создать схему. Есть инструменты, которые могут генерировать схему из документа XML.

Надеюсь, это поможет … не уверен, что это то, что вы искали.

Помимо использования Stax (что имеет смысл), с StaxMate, вероятно, будет проще ( http://staxmate.codehaus.org/Tutorial ). Просто создайте 2 SMInputCursors и, если потребуется, детский курсор. А затем типичная сортировка слияния с двумя курсорами. Подобно перемещению документов DOM с рекурсивным спусками.

Итак, вы заинтересованы только в объединении элементов «результатов»? Все остальное игнорируется? Тот факт, что input0 имеет и input1, имеет , и ожидаемый результат имеет , кажется, предлагает это.

Если вы не беспокоитесь о масштабировании и хотите быстро решить эту проблему, я бы предложил написать конкретный бит кода, который использует простую библиотеку типа JDOM для рассмотрения входов и записи результата вывода.

Попытка написать общий инструмент, который был «умным», достаточным для обработки всех возможных случаев слияния, был бы довольно трудоемким – вам нужно было бы предоставить возможность конфигурации для определения правил слияния. Если вы точно знаете, как будут выглядеть ваши данные, и вы точно знаете, как должно выполняться слияние, я бы предположил, что ваш алгоритм будет выполнять каждый вход XML и записывать на один вывод XML.

Вы можете попробовать Dom4J, который предоставляет очень хорошие средства для извлечения информации с помощью запросов XPath, а также позволяет легко писать XML. Вам просто нужно немного поиграть с API, чтобы выполнить свою работу

Иногда вам нужно просто конкатенировать XML-файлы в один, например, с аналогичной структурой, например:

Файл xml1 :

   ...    ...   

Файл xml2 :

   ...    ...   

В этом случае следующая процедура, использующая библиотеку jdom2 может помочь вам:

 void concatXML(Path fSource,Path fDest) { Document jdomSource = null; Document jdomDest = null; List elems = new LinkedList(); SAXBuilder jdomBuilder = new SAXBuilder(); try { jdomSource = jdomBuilder.build(fSource.toFile()); jdomDest = jdomBuilder.build(fDest.toFile()); Element root = jdomDest.getRootElement(); root.detach(); String sourceNextElementName=((Element) jdomSource.getRootElement().getContent().get(1)).getName(); for (Element record:jdomSource.getRootElement().getDescendants(new ElementFilter(sourceNextElementName))) elems.add(record); for (Element elem : elems) (elem).detach(); root.addContent(elems); Document newDoc = new Document(root); XMLOutputter xmlOutput = new XMLOutputter(); xmlOutput.output(newDoc, System.out); xmlOutput.setFormat(Format.getPrettyFormat()); xmlOutput.output(newDoc, Files.newBufferedWriter(fDest, Charset.forName("UTF-8"))); } catch (Exception e) { e.printStackTrace(); } } 

Считаете ли вы, что вы просто не разбираетесь в синтаксическом анализе XML «правильно» и просто обрабатываете файлы как большие длинные строки и используете скучные старые вещи, такие как хеш-карты и регулярные выражения …? Это может быть один из тех случаев, когда причудливые акронимы с X в них просто делают работу более запутанной, чем это должно быть.

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

  • Как остановить анализ XML-документа с помощью SAX в любое время?
  • NSXMLParser на iPhone, как я его использую, учитывая xml-файл (newb здесь: \)
  • Параметры макета Android XML не работают, как ожидалось
  • Передача параметров в таблицу стилей XSLT через .NET
  • XPath выбирает все элементы между двумя конкретными элементами
  • Регулярное выражение \ p {L} и \ p {N}
  • Удалить 'standalone = "yes" из созданного XML
  • Как распечатать С помощью XDocument
  • как динамически обновлять xml-файл из другого XML-файла?
  • Текст в WordTrap для Android Word
  • Как выравнивать представления в нижней части экрана?
  • Давайте будем гением компьютера.