2013-05-31 2 views
1

Мне нужно скрыть элемент, когда атрибут присутствует в записи. Когда атрибуты cols присутствуют, оставшиеся пустые записи должны быть скрыты в одной строке. Когда присутствует атрибут morerows, тогда запись, присутствующая в следующей строке того же столбца, должна быть удалена.Удалить элемент на основе атрибута с помощью 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 "' в своем коде, означает ли это, что вы можете использовать Процессор XSLT 2.0, такой как Saxon 9 или AltovaXML, решил это? –

ответ

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> 

Однако я только проверил, что на маленьком образце вы предоставили, поэтому, когда я использую Saxon 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> 

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

+0

Большое спасибо за ваш ответ, я проверил и обновил статус – siva2012

+0

Апология для позднего ответа. Я проверил ваш код и его работоспособность для текущего XML. Но я не смог удалить элементы ввода, когда появилось более одного атрибута morerows, как вы сказали – siva2012

+0

Я думаю, что он работает до тех пор, пока существует одна «запись» с атрибутом «morerows» на «row». Однако требуется больше работы, если может быть более одной «записи» с атрибутом «morerows» для каждой строки. У меня не будет времени, чтобы попытаться решить и реализовать это, извините. Может быть, кто-то может помочь вам. –

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