2016-08-17 3 views
0

У меня есть XML-файл с множеством вложенных элементов темы. Например:Разделение элементов в XML на отдельные файлы

<?xml version="1.0" encoding="UTF-8"?> 
<topic id="topic-1"> 
    <title>ADBT</title> 

    <para>The program executes a database request by using the ADBT 
     library. The ADBT library prepares 
     the request and calls an ODBC driver 
     or a native API.   
    </para> 

    <topic id="topic_wom_eqy_ev"> 
     <title>Establishing a connection</title> 
     <para> 
      In order to use a database with ADBT, the first step to be taken 
      is 
      to establish a 
      connection. 
     </para> 

    </topic> 
    <topic id="topic_dsw_gqy_ev"> 
     <title>Querying a database</title> 
     <para>Querying a database involves a number of stages.</para> 
     <topic id="topic_ljf_isy_ev"> 
      <title>Stage one: create a query</title> 
      <para> A new query (ADBT_Select object) can only be created starting 
       from a previously 
       established connection. A query is created using 
       the CreateSelect method in two 
       different 
       ways: 
      </para> 
     </topic> 
    </topic> 

</topic> 

Я хочу, чтобы каждый из тем, которые будут выделены в новый файл XML с именем файла таким же, как название. Если тема содержит другую тему, эта тема будет отдельным файлом, а родительская тема будет отдельным файлом с содержимым, исключающим дочерний раздел. К примеру, в этом случае будет четыре файла, как выход со следующим содержанием:

Номер 1:

<topic id="topic-1"> 
     <title>ADBT</title> 

     <para>The program executes a database request by using the ADBT 
      library. The ADBT library prepares 
      the request and calls an ODBC driver or a native API.   
     </para> 
    </topic> 

Номер 2:

<topic id="topic_wom_eqy_ev"> 
     <title>Establishing a connection</title> 
     <para> 
      In order to use a database with ADBT, the first step to be taken is 
      to establish a 
      connection. 
     </para>  

    </topic> 

Номер 3:

<topic id="topic_dsw_gqy_ev"> 
     <title>Querying a database</title> 
     <para>Querying a database involves a number of stages.</para> 
</topic> 

Номер 4:

<topic id="topic_ljf_isy_ev"> 
      <title>Stage one: create a query</title> 
      <para> A new query (ADBT_Select object) can only be created starting 
       from a previously 
       established connection. A query is created using the CreateSelect method in two 
       different 
       ways: 
      </para> 
      </topic> 

Я написал несколько функций, но я не могу понять, как отделить многоуровневые вложенные темы.

+0

вы используете процессор XSLT 2.0, как Saxon 9, так что вы можете использовать 'xsl: result-document' для записи нескольких файлов? –

ответ

1

В принципе, то, что вы хотите сделать, это:

  • читать XML с помощью чтения XML вашего выбора
  • получить все <topic> элементы в документе рекурсивно
  • для каждого <topic> элемента, создать копия этого элемента (возможно, новый документ для каждого из них с корнем из него является элементом <topic>), копируя все дочерние элементы из оригинала, но дети, у которых есть tagName = topic. Это гарантирует, что рекурсивные вызовы не будут давать пересекающиеся элементы
  • для каждого из таких созданных Document с, сериализовать его в файл с помощью XML писателя вашего выбора

Таким образом, для схематического кода:

Document document = readXMLDocument(...); 
List<Element> topicElements = readTopicElementsRecursively(document); 
List<Document> splitTopicDocuments = new ArrayList<>(); 
for (Element el : topicElements) { 
    Document doc = copyElementWithoutTopicChildren(el); 
    splitTopicDocuments.add(doc); 
} 
writeTopicDocuments(splitTopicDocuments); 
1

Использование XSLT 2.0, как доступный для Java с Saxon 9 вы можете использовать

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs" 
    version="2.0"> 

    <xsl:template match="/"> 
     <xsl:for-each select="//topic"> 
      <xsl:result-document href="topic{position()}.xml"> 
       <xsl:call-template name="identity"/> 
      </xsl:result-document>   
     </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="@* | node()" name="identity"> 
     <xsl:copy> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="topic"/> 

</xsl:stylesheet> 
+0

Мартин. Вам нужны ваши данные для другого вопроса. Не могли бы вы помочь http://stackoverflow.com/questions/38993864/match-and-merge-in-xslt-with-optional-nodes – Victor

+0

Чтобы сделать имя файла таким же, как название темы (по запросу), вы можете do 'href =" {title} .xml "', хотя это немного сомнительно, поскольку href должен быть URI, а пробелы в URI не разрешены; это также вызовет ошибку, если названия не уникальны. –

Смежные вопросы