2015-01-27 4 views
1

Я пытаюсь извлечь TOC из файла document.xml DOCX, используя XSLTXSLT прочитать таблицу содержимого из DOCX document.xml

Вот мой XSLT:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sap="http://www.sap.com/sapxsl" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" exclude-result-prefixes="w" version="2.0"> 
    <xsl:output indent="yes" method="xml"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="w:sdt"> 
     <xsl:element name="root"> 

      <xsl:attribute name="label"> 
      <xsl:value-of select="w:sdtPr/w:docPartObj/w:docPartGallery/@w:val"/> 
      </xsl:attribute> 

      <xsl:for-each select="w:sdtContent/w:p"> 
      <xsl:if test="w:pPr/w:pStyle/@w:val"> 

       <xsl:element name="sec"> 

       <xsl:attribute name="label"> 
        <xsl:value-of select="w:pPr/w:pStyle/@w:val"/> 
       </xsl:attribute> 

       <xsl:attribute name="anchor"> 
        <xsl:value-of select="w:hyperlink/@w:anchor"/> 
       </xsl:attribute> 

       <xsl:attribute name="title"> 
        <xsl:value-of select="w:hyperlink/w:r/w:t"/> 
       </xsl:attribute> 

       </xsl:element> 

      </xsl:if> 
      </xsl:for-each> 
     </xsl:element> 
     </xsl:if> 
    </xsl:template> 
</xsl:transform> 

я получаю желаемый результат но с дополнительными значениями w: p tag вне области w: sdtContent.

Я новичок в XSLT и не уверен, что я делаю неправильно здесь.

(если источник XML поможет, пожалуйста, дайте мне знать, я отправлю его здесь.)

+0

Ваш XSLT синтаксически недействителен. Сначала исправьте это. – Tomalak

ответ

2

XSLT обрабатывает входные данные, начиная с корневого узла, с a set of default rules. Эти правила по умолчанию можно переопределить, но вы этого не сделаете. Я подозреваю, что нежелательный дополнительный вывод, который вы видите, исходит из правил по умолчанию.

Ваша таблица стилей содержит шаблон <xsl:template match="w:sdt"> и XSLT процессор делает запустить этот шаблон, но только тогда, когда он попадает в <w:sdt> в то время как он проходит входной документ.

Если вы хотите начать с корневого узла самостоятельно и диктовать какие узлы процессор XSLT должен смотреть, изменить поведение по умолчанию, написав шаблон, соответствующий корневой узел (<xsl:template match="/">).

<xsl:transform 
    version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:sap="http://www.sap.com/sapxsl" 
    xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" 
    exclude-result-prefixes="w" 
> 
    <xsl:output indent="yes" method="xml" /> 
    <xsl:strip-space elements="*" /> 

    <xsl:template match="/"> 
    <xsl:apply-temmplates select="//w:sdt" /> 
    </xsl:template> 

    <xsl:template match="w:sdt"> 
    <root label="{w:sdtPr/w:docPartObj/w:docPartGallery/@w:val}" /> 
     <xsl:apply-templates select="w:sdtContent/w:p[w:pPr/w:pStyle/@w:val]" /> 
    </root> 
    </xsl:template> 

    <xsl:template match="w:sdtContent/w:p"> 
    <sec 
     label="{w:pPr/w:pStyle/@w:val}" 
     anchor="{w:hyperlink/@w:anchor}" 
     title="{w:hyperlink/w:r/w:t}" 
    /> 
    </xsl:template> 
</xsl:transform> 

Другие ноты:

  • Не писать <xsl:element name="foo">. Напишите <foo>.
  • Не писать <xsl:attribute name="bar"> Написать <foo bar="{xpath-expr}">.
  • Избегать <xsl:for-each>. Используйте <xsl:apply-templates> и <xsl:template>.
  • Избегайте <xsl:if> для фильтрации тех узлов, которые вы хотите обработать. Напишите соответствующее выражение XPath, которое выбирает только узлы, которые вы хотите обработать.
  • Положительно полезно прочитать: How <xsl:apply-templates> works.
+0

Хороший код и объяснение, +1. –

+0

Tomalak, Большое спасибо за объяснения и код. Также спасибо за очень полезные ссылки. – athavanraja