Преобразование таблицы DOCX в XML с помощью XSL

#xml #xslt #docx

#xml #xslt #docx

Вопрос:

У меня есть файл docx с таблицей рабочего расписания, например:

         monday | tuesday | wednesday | thursday | friday | saturday | sunday
Peter     5    |   4     |           |    6     |   5    |          |   11
John      2    |         |    1      |    6     |   5    |     4    |
etc..
  

Я извлек document.xml из docx и пытаюсь создать следующий xml, используя этот xml.

 <schedule>
   <monday>
     <shift name="Peter" time="5" />
     <shift name="John"  time="2" />
   </monday>
   <tuesday>
 etc...
  

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

 <schedule>
   <monday>
     <shift name="Peter" time="5" />
   </monday>
   <monday>
     <shift name="John"  time="2" />
   </monday>
   <tuesday>
etc..
  

Как мне это исправить?

Вложения: document.xml (извлечено из docx) ВОТ xsl, который я создал ЗДЕСЬ

Комментарии:

1. Это правильный XML-документ, который вы предоставили? Это больше похоже на ваш текущий выходной XML, в отличие от входного XML-документа.

2. Я обновил xml, к нему уже был применен xsl. Теперь оригинал находится в сети.

3. Вы не предоставили исходный XML !. Пожалуйста, отредактируйте вопрос и предоставьте его.

4. Я связал исходный XML в нижней части моего вопроса. Вот ссылка снова: ссылка

Ответ №1:

Примените к вашему текущему результату это преобразование (группировка по Мюнх):

 <xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:key name="kDayByName" match="/*/*" use="name()"/>

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

 <xsl:template match="/*/*"/>

 <xsl:template match=
  "/*/*[generate-id()
       =
        generate-id(key('kDayByName', name())[1])
       ]
  ">

  <xsl:copy>
    <xsl:apply-templates select=
        "key('kDayByName', name())/node()"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>
  

при применении к этому XML-документу:

 <schedule>
    <monday>
        <shift name="Peter" time="5" />
    </monday>
    <monday>
        <shift name="John"  time="2" />
    </monday>
</schedule>
  

получен требуемый правильный результат:

 <schedule>
    <monday>
        <shift name="Peter" time="5" />
        <shift name="John" time="2" />
    </monday>
</schedule>
  

Комментарии:

1. Это сработало отлично! Один маленький вопрос: как мне применить несколько таблиц стилей XSL без сохранения результата первой. Я работаю на PHP. Большое вам спасибо!

2. @user189172: обычно возникает несколько вопросов о «многоходовом преобразовании»: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:variable name="vrtfPass1"> <xsl:apply-templates select="/*"/> </xsl:variable> <xsl:variable name="vPass1" select="ext:node-set($vrtfPass1)"/> <xsl:template match="/"> <xsl:apply-templates select="$vPass1" mode="pass2"/> </xsl:template> </xsl:stylesheet>

3. Спасибо за вашу помощь, я боролся с вашим многоходовым кодом, но пока не смог заставить его работать. Я не знаю, где я должен разместить XSl в этом коде. Я много искал в Google, но примеры очень сложные. Не могли бы вы мне еще раз помочь?