2013-05-31 68 views
1

當需要隱藏元素時,當屬性出現在條目中時。當屬性列出現時,剩餘的空條目應隱藏在同一行中。當存在更多的屬性時,應刪除同一列下一行中的條目。使用XSLT基於屬性移除元素

樣品輸入:

<?xml version="1.0"?> 
<table> 
<tbody> 
<row> 
<entry cols="2">Row 1 Col 1</entry> 
<entry></entry> 
<entry></entry> 
<entry morerows="2">Row 1 Col 4</entry> 
<entry>Row 1 Col 5</entry> 
</row> 
<row> 
<entry>Row 2 Col 1</entry> 
<entry>Row 2 Col 2</entry> 
<entry>Row 2 Col 3</entry> 
<entry></entry> 
<entry>Row 2 Col 5</entry> 
</row> 
<row> 
<entry>Row 3 Col 1</entry> 
<entry>Row 3 Col 2</entry> 
<entry>Row 3 Col 3</entry> 
<entry></entry> 
<entry>Row 3 Col 5</entry> 
</row> 
</tbody> 
</table> 

輸出:

<?xml version="1.0"?> 
<table> 
<tbody> 
<row> 
<entry cols="2">Row 1 Col 1</entry> 
<entry morerows="2">Row 1 Col 4</entry> 
<entry>Row 1 Col 5</entry> 
</row> 
<row> 
<entry>Row 2 Col 1</entry> 
<entry>Row 2 Col 2</entry> 
<entry>Row 2 Col 3</entry> 
<entry>Row 2 Col 5</entry> 
</row> 
<row> 
<entry>Row 3 Col 1</entry> 
<entry>Row 3 Col 2</entry> 
<entry>Row 3 Col 3</entry> 
<entry>Row 3 Col 5</entry> 
</row> 
</tbody> 
</table> 

XSLT嘗試:

<?xml version='1.0'?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:mml="http://www.w3.org/1998/Math/MathML"> 
<xsl:output method="xml" encoding="UTF-8" indent="no"/> 

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

<xsl:template match="row"> 
<xsl:copy> 
<xsl:for-each select="entry"> 
<xsl:if test="@cols"><xsl:variable name="span_cols" select="@cols+1"/></xsl:if> 
<xsl:apply-templates select="following-sibling::*[$span_cols]"/> 
</xsl:for-each> 
<xsl:apply-templates select="@*|node()"/> 
</xsl:copy> 
</xsl:template> 


<xsl:template match="entry"> 
<xsl:choose> 
<xsl:when test="@cols"> 
<xsl:copy> 
<xsl:variable name="current_colno" select="count(preceding-sibling::entry)+1"/> 
<xsl:variable name="span_cols" select="@cols+1"/> 
<xsl:attribute name="namest"><xsl:value-of select="$current_colno"/></xsl:attribute> 
<xsl:attribute name="nameend"><xsl:value-of select="sum($span_cols,$current_colno)"/></xsl:attribute> 
</xsl:copy> 
</xsl:when> 
<xsl:otherwise><xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy></xsl:otherwise> 
</xsl:choose> 
</xsl:template> 

</xsl:stylesheet 

>

+0

'@ cols'和'@ morerows'屬性只存在於第一個''中,還是可以在任何地方? – ABach

+0

@ABach:感謝您的回覆'@ cols'和'@ morerows'可能發生在任何地方,並且它可能包含任何值 – siva2012

+0

您在代碼中使用了'version =「2.0」',這是否意味着您可以使用像Saxon 9或AltovaXML這樣的XSLT 2.0處理器來解決這個問題? –

回答

1

我寫它試圖實現轉型的一些代碼三個步驟:

  1. 標誌那些entry元件因爲cols屬性
  2. 標誌那些entry元件因爲morerows屬性
  3. 最後取出被判entry元件

這裏是被刪除的被刪除代碼:

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

<xsl:output indent="yes"/> 

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

<xsl:template match="tbody"> 
    <xsl:copy> 
    <xsl:variable name="cols-flagged-to-delete" as="element(tbody)"> 
     <xsl:copy> 
     <xsl:apply-templates select="*" mode="flag-to-delete-col"/> 
     </xsl:copy> 
    </xsl:variable> 
    <xsl:variable name="rows-flagged-to-delete" as="element(row)*"> 
     <xsl:apply-templates select="$cols-flagged-to-delete" mode="flag-to-delete-row"/> 
    </xsl:variable> 
    <xsl:apply-templates select="$rows-flagged-to-delete" mode="delete"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="tbody/row" mode="flag-to-delete-col"> 
    <xsl:copy> 
    <xsl:for-each-group select="entry" group-starting-with="entry[@cols]"> 
     <xsl:choose> 
     <xsl:when test="self::entry[@cols]"> 
      <xsl:variable name="cols" as="xs:integer" select="xs:integer(@cols)"/> 
      <xsl:apply-templates select="."/> 
      <xsl:apply-templates select="current-group()[not(node()) and position() gt 1 and position() le (1 + $cols)]" 
      mode="flag-to-delete-col"/> 
      <xsl:apply-templates select="current-group()[position() gt (1 + $cols)]"/> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:apply-templates select="current-group()"/> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:for-each-group> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="tbody/row/entry" mode="flag-to-delete-col flag-to-delete-row"> 
    <entry delete="true"/> 
</xsl:template> 

<xsl:template match="tbody" mode="flag-to-delete-row"> 
    <xsl:for-each-group select="row" group-starting-with="row[entry/@morerows]"> 
    <xsl:choose> 
     <xsl:when test="self::row[entry/@morerows]"> 
     <xsl:variable name="pos" as="xs:integer" select="count(entry[@morerows]/preceding-sibling::entry) + 1"/> 
     <xsl:variable name="n" as="xs:integer" select="xs:integer(entry/@morerows)"/> 
     <xsl:apply-templates select="current-group()" mode="flag-to-delete-row"> 
      <xsl:with-param name="pos" select="$pos"/> 
      <xsl:with-param name="n" select="$n"/> 
     </xsl:apply-templates> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:apply-templates select="current-group()"/> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:for-each-group> 
</xsl:template> 

<xsl:template match="tbody/row" mode="flag-to-delete-row"> 
    <xsl:param name="pos"/> 
    <xsl:param name="n"/> 
    <xsl:copy> 
    <xsl:choose> 
     <xsl:when test="position() gt 1 and position() le (1 + $n)"> 
     <xsl:apply-templates select="entry[position() lt $pos]"/> 
     <xsl:apply-templates select="entry[$pos]" mode="flag-to-delete-row"/> 
     <xsl:apply-templates select="entry[position() gt $pos]"/> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:apply-templates select="entry"/> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="row/entry[@delete = 'true']" mode="delete"/> 

</xsl:stylesheet> 

不過我只測試了在小樣本您提供,所以當我使用撒克遜9.5改造

<?xml version="1.0"?> 
<table> 
    <tbody> 
    <row> 
     <entry cols="2">Row 1 Col 1</entry> 
     <entry></entry> 
     <entry></entry> 
     <entry morerows="2">Row 1 Col 4</entry> 
     <entry>Row 1 Col 5</entry> 
    </row> 
    <row> 
     <entry>Row 2 Col 1</entry> 
     <entry>Row 2 Col 2</entry> 
     <entry>Row 2 Col 3</entry> 
     <entry></entry> 
     <entry>Row 2 Col 5</entry> 
    </row> 
    <row> 
     <entry>Row 3 Col 1</entry> 
     <entry>Row 3 Col 2</entry> 
     <entry>Row 3 Col 3</entry> 
     <entry></entry> 
     <entry>Row 3 Col 5</entry> 
    </row> 
    </tbody> 
</table> 

我確實得到

<table> 
    <tbody> 
     <row> 
     <entry cols="2">Row 1 Col 1</entry> 
     <entry morerows="2">Row 1 Col 4</entry> 
     <entry>Row 1 Col 5</entry> 
     </row> 
     <row> 
     <entry>Row 2 Col 1</entry> 
     <entry>Row 2 Col 2</entry> 
     <entry>Row 2 Col 3</entry> 
     <entry>Row 2 Col 5</entry> 
     </row> 
     <row> 
     <entry>Row 3 Col 1</entry> 
     <entry>Row 3 Col 2</entry> 
     <entry>Row 3 Col 3</entry> 
     <entry>Row 3 Col 5</entry> 
     </row> 
    </tbody> 
</table> 

但需要更復雜的輸入和輸出樣本我認爲要測試代碼,所以請做到這一點,並報告回來。並且我假定在每個row元素的entry元素內部不存在多於一個morerows屬性,我不確定該假設適用於您的輸入要求。

+0

非常感謝您的回覆,我會檢查並更新狀態 – siva2012

+0

對於遲到的回覆道歉。我測試了你的代碼,並且對當前的XML工作正常。但是,如果你說的多於一個morerows屬性發生,我不能刪除條目元素。 – siva2012

+0

我認爲只要每個'row'有一個'entry'屬性和'morerows'屬性,它就會工作。但是,如果每個'row'可以有多個'entry'屬性並且'morerows'屬性,那麼需要做更多的工作。我沒有時間去嘗試解決和實施這個,對不起。也許別人能夠幫助你。 –