2017-01-01 8 views
-1

Учитывая это Open XML фрагмент:Как вывести больше столбцов, чем вход

<?xml version="1.0"?> 
<?mso-application progid="Excel.Sheet"?> 
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" 
    xmlns:o="urn:schemas-microsoft-com:office:office" 
    xmlns:x="urn:schemas-microsoft-com:office:excel" 
    xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" 
    xmlns:html="http://www.w3.org/TR/REC-html40"> 

    <Worksheet ss:Name="Sheet5"> 
     <Table ss:ExpandedColumnCount="7" ss:ExpandedRowCount="4"> 
     <Column ss:Index="2" ss:AutoFitWidth="0" ss:Width="59.25"/> 
     <Column ss:Index="5" ss:AutoFitWidth="0" ss:Width="75"/> 
     <Column ss:AutoFitWidth="0" ss:Width="31.5"/> 
     </Table> 
    </Worksheet> 

</Workbook> 

... что XSLT 1.0 решения шаблонного (избегая петлю, если это возможно), я могу использовать для получения этого вывода HTML фрагмента:

<table> 
    <colgroup> 
    <col style="width:45pt;"> 
    <col style="width:59.25pt;"> 
    <col style="width:45pt;"> 
    <col style="width:45pt;"> 
    <col style="width:75pt;"> 
    <col style="width:31.5pt;"> 
    <col style="width:45pt;"> 
    </colgroup> 
</table> 

Обратите внимание, что атрибут ss: ExpandedColumnCount указывает общее количество столбцов. Также обратите внимание, что a Столбец тег в источнике, который не включает ss: Индекс - это особый случай, который указывает следующий индекс столбца после предыдущего индекса; в этом случае он оценивается до 6. Все остальные столбцы принимают ширину 45pt.

В моей среде нет выбора, кроме использования MSXML2 Engine.

Это просто произвольный пример выбора диапазона на листе MS Excel, закодированном в Open XML, иногда называемом OOXML. Я ищу XLST, чтобы выполнить это преобразование в общем случае.

+0

Откуда взялось значение '75pt'? –

+0

Нам нужен более полный фрагмент XML, чтобы узнать, где объявлено пространство имен * ss *. – Parfait

+0

@ michael.hor257k Это опечатка. Исправлена. –

ответ

0

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

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" 
    exclude-result-prefixes="ss"> 
<xsl:output method="xml" indent="yes"/> 

<xsl:template match="ss:Table"> 
    <table> 
     <colgroup> 
      <xsl:call-template name="Columns" /> 
     </colgroup> 
    </table> 
</xsl:template> 

<xsl:template name="Columns"> 
    <xsl:param name="MaxColumns" select="@ss:ExpandedColumnCount" /> 
    <xsl:param name="Column" select="ss:Column[1]" /> 
    <xsl:param name="ColumnNumber" select="1" /> 

    <xsl:if test="$ColumnNumber &lt;= $MaxColumns"> 
    <xsl:variable name="IsMatch" select="$Column/@ss:Index = $ColumnNumber or $Column[not(@ss:Index)]" /> 
    <xsl:variable name="width"> 
     <xsl:choose> 
     <xsl:when test="$IsMatch"> 
      <xsl:value-of select="$Column/@ss:Width" /> 
     </xsl:when> 
     <xsl:otherwise>45</xsl:otherwise> 
     </xsl:choose> 
    </xsl:variable> 
    <col style="width:{$width}pt;"></col> 
    <xsl:call-template name="Columns"> 
     <xsl:with-param name="MaxColumns" select="$MaxColumns" /> 
     <xsl:with-param name="Column" select="$Column[not($IsMatch)]|$Column[$IsMatch]/following-sibling::ss:Column[1]" /> 
     <xsl:with-param name="ColumnNumber" select="$ColumnNumber + 1" /> 
    </xsl:call-template> 
    </xsl:if> 
</xsl:template> 
</xsl:stylesheet> 
+0

Это сработало. И мне нравится тот факт, что ti не полагается на расширение. –

2

Я не уверен, что именно вы подразумеваете под «, избегая петель, если возможно». Я, конечно, не вижу, как это можно сделать без использования рекурсии. На самом деле, я считаю, нужно использовать его в двух местах:

  • первым, чтобы создать список перекрывая ширину столбцов, где каждый узел имеет значение индекса;

  • затем, чтобы сгенерировать необходимое количество элементов col.

XSLT 1,0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" 
exclude-result-prefixes="ss" 
xmlns:exsl="http://exslt.org/common" 
extension-element-prefixes="exsl"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="ss:Table"> 
    <xsl:variable name="col-widths-rtf"> 
     <xsl:apply-templates select="ss:Column[1]" mode="col-widths"/> 
    </xsl:variable> 
    <table> 
     <colgroup> 
      <xsl:call-template name="colgroup"> 
       <xsl:with-param name="n" select="@ss:ExpandedColumnCount"/> 
       <xsl:with-param name="col-widths" select="exsl:node-set($col-widths-rtf)/width"/> 
      </xsl:call-template> 
     </colgroup> 
    </table> 
</xsl:template> 

<xsl:template match="ss:Column" mode="col-widths"> 
    <xsl:param name="last-index" select="0"/> 
    <xsl:variable name="index"> 
     <xsl:choose> 
      <xsl:when test="@ss:Index"> 
       <xsl:value-of select="@ss:Index"/> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="$last-index + 1"/> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:variable> 
    <width index="{$index}"> 
     <xsl:value-of select="@ss:Width"/> 
    </width> 
    <!-- sibling recursion --> 
    <xsl:apply-templates select="following-sibling::ss:Column[1]" mode="col-widths"> 
     <xsl:with-param name="last-index" select="$index"/> 
    </xsl:apply-templates> 
</xsl:template> 

<xsl:template name="colgroup"> 
    <xsl:param name="n"/> 
    <xsl:param name="col-widths"/> 
    <xsl:variable name="override" select="$col-widths[@index=$n]" /> 
    <xsl:variable name="width"> 
     <xsl:choose> 
      <xsl:when test="$override"> 
       <xsl:value-of select="$override"/> 
      </xsl:when> 
      <xsl:otherwise>45</xsl:otherwise> 
     </xsl:choose>  
    </xsl:variable> 
    <xsl:if test="$n > 1"> 
     <!-- recursive call --> 
     <xsl:call-template name="colgroup"> 
      <xsl:with-param name="n" select="$n - 1"/> 
      <xsl:with-param name="col-widths" select="$col-widths"/> 
     </xsl:call-template> 
    </xsl:if> 
    <col style="width:{$width}pt;"/> 
</xsl:template> 

</xsl:stylesheet> 
+0

Хороший ответ! Этот процесс рекурсивного вызова шаблонов похож на ответ, который вы дали по моему вопросу при переносе [Google Doodles] (http://stackoverflow.com/questions/38707512/xml-to-csv-transpose-by-dates). Без сомнения, подпись @ michael.hor257k! – Parfait

+0

Отличный ответ, но, поскольку он стоит, это не сработает для меня. Я вынужден использовать MSXML2 для преобразования и, видимо, не поддерживает расширение. Может ли ваш ответ быть переработан без расширений? –

+0

@astudent Посмотрите, поддерживает ли она ту же функцию в пространстве имен msxsl: https://msdn.microsoft.com/en-us/library/hz88kef0%28v=vs.110%29.aspx –

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