2013-06-17 2 views
0

Я преобразовываю файлы XML, которые не содержат каждый элемент схемы. Какую технику я должен использовать в своем XSLT-файле, чтобы полученный XML-файл содержал все элементы, указанные в схеме?Создание XSLT 1.0 Создание XML с учетом схемы

Я знаю, что XSLT 2.0 может решить эту проблему легко, но я застрял с XSLT 1.0.

Пол


Вот пример того, что я пытаюсь сделать:

Schema.xml

<SAN> 
    <STACKMEMBERS> 
     <STACKMEMBER> 
      <A/> 
      <B/> 
      <ETHERNETSWITCHES> 
       <ETHERNETSWITCH> 
        <C/> 
        <D/> 
        <E/> 
       </ETHERNETSWITCH> 
      </ETHERNETSWITCHES> 
     </STACKMEMBER> 
    </STACKMEMBERS> 
</SAN> 

DataFile.xml

<SAN> 
    <STACKMEMBERS> 
     <STACKMEMBER> 
      <A>1111</A> 
      <ETHERNETSWITCHES> 
       <ETHERNETSWITCH> 
        <D>3333</D> 
        <E>4444</E> 
       </ETHERNETSWITCH> 
       <ETHERNETSWITCH> 
        <D>5555</D> 
        <E>6666</E> 
       </ETHERNETSWITCH> 
      </ETHERNETSWITCHES> 
     </STACKMEMBER> 
     <STACKMEMBER> 
      <A>2222</A> 
      <ETHERNETSWITCHES> 
       <ETHERNETSWITCH> 
        <D>7777</D> 
        <E>8888</E> 
       </ETHERNETSWITCH> 
       <ETHERNETSWITCH> 
        <D>9999</D> 
        <E>1010</E> 
       </ETHERNETSWITCH> 
      </ETHERNETSWITCHES> 
     </STACKMEMBER> 
    </STACKMEMBERS> 
</SAN> 

Желаемая Выход:

<SAN> 
    <STACKMEMBERS> 
     <STACKMEMBER> 
      <A>1111</A> 
      <B /> 
      <ETHERNETSWITCHES> 
       <ETHERNETSWITCH> 
        <C /> 
        <D>3333</D> 
        <E>4444</E> 
       </ETHERNETSWITCH> 
       <ETHERNETSWITCH> 
        <C /> 
        <D>5555</D> 
        <E>6666</E> 
       </ETHERNETSWITCH> 
      </ETHERNETSWITCHES> 
     </STACKMEMBER> 
     <STACKMEMBER> 
      <A>2222</A> 
      <B /> 
      <ETHERNETSWITCHES> 
       <ETHERNETSWITCH> 
        <C />    
        <D>7777</D> 
        <E>8888</E> 
       </ETHERNETSWITCH> 
       <ETHERNETSWITCH> 
        <C /> 
        <D>9999</D> 
        <E>1010</E> 
       </ETHERNETSWITCH> 
      </ETHERNETSWITCHES> 
     </STACKMEMBER> 
    </STACKMEMBERS> 
</SAN> 

Мой текущий файл XSLT является ...

<?xml version="1.0" encoding="windows-1252"?> 

<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:variable name="schemaFile" select="document('Schema.xml')"/> 

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

    <xsl:template match="*"> 
     <SAN> 
      <STACKMEMBERS> 
       <xsl:for-each select="/SAN/STACKMEMBERS/STACKMEMBER"> 
        <xsl:copy-of select="."/> 
        <xsl:copy-of select="$schemaFile/SAN/STACKMEMBERS/STACKMEMBER"/> 
       </xsl:for-each> 
      </STACKMEMBERS> 
     </SAN> 
    </xsl:template> 

</xsl:stylesheet> 

... и это дает мне неправильные результаты:

<SAN> 
    <STACKMEMBERS> 
     <STACKMEMBER> 
      <A>1111</A> 
      <ETHERNETSWITCHES> 
       <ETHERNETSWITCH> 
        <D>3333</D> 
        <E>4444</E> 
        </ETHERNETSWITCH> 
       <ETHERNETSWITCH> 
        <D>5555</D> 
        <E>6666</E> 
       </ETHERNETSWITCH> 
      </ETHERNETSWITCHES> 
     </STACKMEMBER> 
     <STACKMEMBER> 
      <A /> 
      <B /> 
      <ETHERNETSWITCHES> 
       <ETHERNETSWITCH> 
        <C /> 
        <D /> 
        <E /> 
       </ETHERNETSWITCH> 
      </ETHERNETSWITCHES> 
     </STACKMEMBER> 
     <STACKMEMBER> 
      <A>2222</A> 
      <ETHERNETSWITCHES> 
       <ETHERNETSWITCH> 
        <D>7777</D> 
        <E>8888</E> 
       </ETHERNETSWITCH> 
       <ETHERNETSWITCH> 
        <D>9999</D> 
        <E>1010</E> 
       </ETHERNETSWITCH> 
      </ETHERNETSWITCHES> 
     </STACKMEMBER> 
     <STACKMEMBER> 
      <A /> 
      <B /> 
      <ETHERNETSWITCHES> 
       <ETHERNETSWITCH> 
        <C /> 
        <D /> 
        <E /> 
       </ETHERNETSWITCH> 
      </ETHERNETSWITCHES> 
     </STACKMEMBER> 
    </STACKMEMBERS> 
</SAN> 

Примечание что элементы B и C определены в схеме, но не представлены в файле данных. Желаемый результат должен добавлять элементы, содержащиеся только в схеме, в файл данных.

Было бы неплохо иметь несколько критериев для выбора (например, select = (один, два)). Я чувствую, что я рядом, но нуждаюсь в небольшом нажатии, чтобы получить желаемый результат.

Пол


Вот полный XSLT-файл, переработанный с шаблоном Майкла Кея, что это не совсем рабочий:

<?xml version="1.0" encoding="windows-1252"?> 

<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

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

    <xsl:variable name="Instance" select="/"/> 
    <xsl:variable name="Schema" select="document('schema.xml')"/> 

    <xsl:template match="*"> 
     <xsl:copy> 
      <xsl:variable name="E" select="."/> 
      <xsl:variable name="S" select="$Schema//*[name(.)=name($E)]"/> 
      <xsl:for-each select="$S/*"> 
       <xsl:variable name="SC" select="."/> 
       <xsl:variable name="EC" select="$E/*[name(.)=name($SC)]"/> 
       <xsl:choose> 
        <xsl:when test="$EC"> 
         <xsl:apply-templates select="$EC"/> 
        </xsl:when> 
        <xsl:otherwise> 
         <xsl:copy-of select="$SC"/> 
        </xsl:otherwise> 
       </xsl:choose> 
      </xsl:for-each> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

Я написал шаблон, который должен возвращать элемент XPath. Затем я модифицировал приведенный выше шаблон, чтобы искать элементы XPath вместо имени элемента. Результатом является переполнение стека, и я не знаю, где я ошибся.

Это код XSLT, который не работает. Любая помощь приветствуется.

Пол

<?xml version="1.0"?> 

<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2011-03-16T10:53:27"> 

    <xsl:output indent="yes"/> 
     <xsl:strip-space elements="*"/> 

     <xsl:variable name="Data" select="/"/> 
     <xsl:variable name="Schema" select="document('MainDataSource.xml')"/> 

    <xsl:template match="*[not(*)]"> 
     <xsl:copy-of select="."/> 
    </xsl:template> 

     <xsl:template name="GetXPath"> 
       <xsl:param name="element"/> 
       <xsl:if test="not(*)"> 
         <xsl:apply-templates select="ancestor-or-self::*" mode="path"/> 
       </xsl:if> 
     </xsl:template> 

     <xsl:template match="*" mode="path"> 
       <xsl:value-of select="concat('/',name())"/> 
     </xsl:template> 

     <xsl:template match="*"> 
       <xsl:copy> 
         <xsl:variable name="DataElement" select="."/> 

         <xsl:variable name="DataElementXPath"> 
           <xsl:call-template name="GetXPath"> 
             <xsl:with-param name="element" select="$DataElement"/> 
           </xsl:call-template> 
         </xsl:variable> 

         <xsl:variable name="SchemaElement" select="$Schema/*[$DataElementXPath]"/> 

         <xsl:for-each select="$SchemaElement/*"> 
           <xsl:variable name="SchemaChild" select="."/> 

           <xsl:variable name="SchemaChildXPath"> 
             <xsl:call-template name="GetXPath"> 
               <xsl:with-param name="element" select="$SchemaChild"/> 
             </xsl:call-template> 
           </xsl:variable> 

           <xsl:variable name="DataChild" select="$Data/*[$SchemaChildXPath]"/> 

           <xsl:choose> 
             <xsl:when test="$DataChild"> 
               <xsl:apply-templates select="$DataChild"/> 
             </xsl:when> 
             <xsl:otherwise> 
               <xsl:copy-of select="$SchemaChild"/> 
             </xsl:otherwise> 
           </xsl:choose> 
         </xsl:for-each> 
       </xsl:copy> 
     </xsl:template> 

</xsl:stylesheet> 
+0

(Не в теме, я сделал двойной прием: я просто читаю Джона Ле Карре «Деликатная истина», в которой главный герой маскируется, как Пол Андерсон). –

ответ

0

Нет простого ответа. Просто напишите преобразование, которое выводит действительный XML.

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

+0

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

0

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

Мне кажется, что правило, которое вы хотите применить это:

Чтобы обработать элемент E с именем N в частности, найти элемент S с именем N в схеме. Для каждого дочернего SC этого элемента схемы, если E имеет дочерний EC с тем же именем, обработчик EC, в противном случае скопируйте SC.

Это приводит к следующему:

<xsl:variable name="Instance" select="/"/> 
<xsl:variable name="Schema" select="doc('schema.xml')"/> 
<xsl:template match="*"> 
    <xsl:copy> 
    <xsl:variable name="E" select="."/> 
    <xsl:variable name="S" select="$Schema//*[name(.)=name($E)]"/> 
    <xsl:for-each select="$S/*"> 
     <xsl:variable name="SC" select="."/> 
     <xsl:variable name="EC" select="$E/*[name(.)=name($SC)]"/> 
     <xsl:choose> 
     <xsl:when test="$EC"> 
      <xsl:apply-templates select="$EC"/> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:copy-of select="$SC"/> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:for-each> 
    </xsl:copy> 
</xsl:template> 

Не тестировалось.

+0

ОК, так это не схема, не так ли? Я работаю с файлом MainDataSource из InfoPath. Да, у меня тоже есть файлы .xsd. Я отвечу на ваше решение завтра. А пока, как вы думаете, было бы проще работать непосредственно из файлов .xsd? Пол Андерсон (не самозванец) –

+0

Нет, работать с файлами XSD было бы намного сложнее. –

+0

Майкл, ваш шаблон прекрасно работает, чтобы правильно захватить элементы из двух файлов XML. Но в элементах, взятых из файла данных, нет значений. В частности, эта строка представляется проблемой: '' –

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