2010-03-08 3 views
1

XSLT를 구현할 때이 문제점에 대한 도움이 필요하므로 SAX 파서를 사용하여이 Java 코드를 이미 구현했지만 사용자가 무언가를 변경해야한다는 번거 로움이 있습니다. .XSLT : 계속 분할하지 않음 요소/그룹화 계속됨 요소

이제 XSLT를 사용하여 컴파일하고 웹 서버에 배포 할 필요가 없습니다. 나는 아래와 같은 XML을 가지고있다.

예 1

<ShotRows> 
    <ShotRow row="3" col="3" bit="1" position="1"/> 
    <ShotRow row="3" col="4" bit="1" position="2"/> 
    <ShotRow row="3" col="5" bit="1" position="3"/> 
    <ShotRow row="3" col="6" bit="1" position="4"/> 
    <ShotRow row="3" col="7" bit="1" position="5"/> 
    <ShotRow row="3" col="8" bit="1" position="6"/> 
    <ShotRow row="3" col="9" bit="1" position="7"/> 
    <ShotRow row="3" col="10" bit="1" position="8"/> 
    <ShotRow row="3" col="11" bit="1" position="9"/> 
</ShotRows> 

출력 1 :

<ShotRows> 
    <ShotRow row="3" colStart="3" colEnd="11" /> 
</ShotRows> 
<!-- because the col is continuous from 3 to 11 --> 

예 2

<ShotRows> 
    <ShotRow row="3" col="3" bit="1" position="1"/> 
    <ShotRow row="3" col="4" bit="1" position="2"/> 
    <ShotRow row="3" col="6" bit="1" position="3"/> 
    <ShotRow row="3" col="7" bit="1" position="4"/> 
    <ShotRow row="3" col="8" bit="1" position="5"/> 
    <ShotRow row="3" col="10" bit="1" position="6"/> 
    <ShotRow row="3" col="11" bit="1" position="7"/> 
    <ShotRow row="3" col="15" bit="1" position="8"/> 
    <ShotRow row="3" col="19" bit="1" position="9"/> 
</ShotRows> 

출력 2 :

<ShotRows> 
    <ShotRow row="3" colStart="3" colEnd="4" /> 
    <ShotRow row="3" colStart="6" colEnd="8" /> 
    <ShotRow row="3" colStart="10" colEnd="11" /> 
    <ShotRow row="3" colStart="15" colEnd="15" /> 
    <ShotRow row="3" colStart="19" colEnd="19" /> 
</ShotRows> 

기본 아이디어는 모든 연속 된 열을 하나의 요소로 그룹화하는 것입니다 (예 : 열 3 - 4, 열 6 - 8, 열 10 - 11, 열 15는 하나 뿐이지 열 19는 하나임). 미리 감사드립니다.

답변

2

자바를 사용하면 Saxon 9 및 XSLT 2.0을 사용할 수

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="2.0"> 

    <xsl:output indent="yes"/> 

    <xsl:template match="ShotRows"> 
    <xsl:copy> 
     <xsl:for-each-group select="ShotRow" group-adjacent="number(@col) - position()"> 
     <ShotRow row="{@row}" colStart="{@col}" colEnd="{@col + count(current-group()) - 1}"/> 
     </xsl:for-each-group> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 
+0

간단하고 우아한 +1.:) – Tomalak

+0

XSLT 2.0은 Saxon.NET을 통해 .NET에서도 사용할 수 있습니다. –

+0

자바에서 Saxon 9.1을 사용하고 있습니다 – Gerald

0

XSLT에서 반복 처리가 자주 발생하기 때문에 다소 복잡합니다.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="xml" indent="yes" /> 

    <xsl:template match="ShotRows"> 
     <xsl:copy> 
      <xsl:apply-templates select="ShotRow[1]" /> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="ShotRow"> 
     <xsl:call-template name="ShotRow"> 
      <xsl:with-param name="start" select="@col" /> 
      <xsl:with-param name="shotrow" select="." /> 
     </xsl:call-template> 
    </xsl:template> 

    <xsl:template name="ShotRow"> 
     <xsl:param name="start" /> 
     <xsl:param name="shotrow" /> 

     <xsl:choose> 
      <xsl:when test="$shotrow/@row = $shotrow/following-sibling::ShotRow[1]/@row and 1 + number($shotrow/@col) = number($shotrow/following-sibling::ShotRow[1]/@col)"> 
       <xsl:call-template name="ShotRow"> 
        <xsl:with-param name="start" select="$start" /> 
        <xsl:with-param name="shotrow" select="$shotrow/following-sibling::ShotRow[1]" /> 
       </xsl:call-template> 

      </xsl:when> 
      <xsl:otherwise> 
       <ShotRow row="{$shotrow/@row}" colStart="{$start}" colEnd="{$shotrow/@col}" /> 
       <xsl:apply-templates select="$shotrow/following-sibling::ShotRow[1]" /> 

      </xsl:otherwise> 
     </xsl:choose> 

    </xsl:template> 

</xsl:stylesheet> 
+0

@Gerald : 나는 게시 된 대안에서보세요. – Tomalak

1

신중하게 만들어진 XPath 식을 사용하면이 작업은 선택 및 복사 작업이 간단합니다.

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
> 
    <xsl:template match="ShotRows"> 
    <xsl:copy> 
     <xsl:apply-templates select="ShotRow[ 
     not(preceding-sibling::ShotRow) 
     or 
     not(@col = preceding-sibling::ShotRow[1]/@col + 1) 
     ]" /> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="ShotRow"> 
    <xsl:copy> 
     <xsl:copy-of select="@row" /> 
     <xsl:attribute name="colStart"> 
     <xsl:value-of select="@col" /> 
     </xsl:attribute> 
     <xsl:attribute name="colEnd"> 
     <xsl:value-of select="(. | following-sibling::ShotRow)[ 
      not(@col = following-sibling::ShotRow[1]/@col - 1) 
     ][1]/@col" /> 
     </xsl:attribute> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

정확히 동일한 출력을 제공합니다.

ShotRow[ 
    not(preceding-sibling::ShotRow) 
    or 
    not(@col = preceding-sibling::ShotRow[1]/@col + 1) 
] 

그리고

  • 하나가 더 이전이 없다 <ShotRow> 모든 노드, 즉 선택 : 제 XPath 표현이다세트
  • 또는 @col의 첫 번째 (또는 유일한) 하나는 각각의 이전의
  • ERGO보다 정확히 하나 더 : 이러한 조건이 내가 모든 표시 한
  • 연속 범위의 시작을 표시 이 #s

아래 두 번째 표현식도 마찬가지입니다 누구를 위해 위치는 작은 좀 더 섬세 :

  • (. | following-sibling::ShotRow) (10)는 현재 노드의 결합이며, 다음의 모든 형제 — 나는 "다음 - 형제 또는-자기"하지만, 불행히도 이러한 축이 존재하지 않는 사용하는 것이다,이 노드의
  • )를 그 @col 사람이 각각의 후속의
  • 에르고 다음 하나도 적은 선택 : 이 상태가 연속 범위의 단부를 나타낸다
  • ,745,151 (이 앞서있는 연속적인 범위의 모든 끝을 선택하는 주) 노드
  • , 그것은 첫 번째 (우리가은 "연속적인 범위의 일단"에 관심이 논리적인지 우리에게 가장 가까운 하나)
  • 내가 누구를이에 대한 모든 위치를 표시 한 소요

    <ShotRows> 
        <ShotRow row="3" col="3" bit="1" position="1"/><!-- #s --> 
        <ShotRow row="3" col="4" bit="1" position="2"/><!-- #e --> 
        <ShotRow row="3" col="6" bit="1" position="3"/><!-- #s --> 
        <ShotRow row="3" col="7" bit="1" position="4"/> 
        <ShotRow row="3" col="8" bit="1" position="5"/><!-- #e --> 
        <ShotRow row="3" col="10" bit="1" position="6"/><!-- #s --> 
        <ShotRow row="3" col="11" bit="1" position="7"/><!-- #e --> 
        <ShotRow row="3" col="15" bit="1" position="8"/><!-- #s #e --> 
        <ShotRow row="3" col="19" bit="1" position="9"/><!-- #s #e --> 
    </ShotRows> 
    

    출력 :

    <ShotRows> 
        <ShotRow row="3" colStart="3" colEnd="4" /> 
        <ShotRow row="3" colStart="6" colEnd="8" /> 
        <ShotRow row="3" colStart="10" colEnd="11" /> 
        <ShotRow row="3" colStart="15" colEnd="15" /> 
        <ShotRow row="3" colStart="19" colEnd="19" /> 
    </ShotRows> 
    
    #e

아래 예와 마찬가지입니다


EDIT - 위의 수정 된 버전은 XSL 키를 사용합니다. 큰 입력 문서의 경우 성능 향상이 눈에 should 것입니다. 주로 kEnd가 처리 시간을 줄 였기 때문입니다. 'kStart'는 너무 많은 영향을 미치지 않으며 코드 대칭을 위해서만 포함되었습니다.

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
> 
    <xsl:key 
    name="kStart" 
    match="ShotRow[ 
     not(preceding-sibling::ShotRow) 
     or 
     not(@col = preceding-sibling::ShotRow[1]/@col + 1) 
    ]" 
    use="generate-id(..)" 
    /> 
    <xsl:key 
    name="kEnd" 
    match="ShotRow[ 
     (. | following-sibling::ShotRow)[ 
     not(@col = following-sibling::ShotRow[1]/@col - 1) 
     ] 
    ]" 
    use="concat(generate-id(..), ':', generate-id())" 
    /> 

    <xsl:template match="ShotRows"> 
    <xsl:copy> 
     <xsl:apply-templates select="key('kStart', generate-id(.))" /> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="ShotRow"> 
    <xsl:copy> 
     <xsl:copy-of select="@row" /> 
     <xsl:attribute name="colStart"> 
     <xsl:value-of select="@col" /> 
     </xsl:attribute> 
     <xsl:attribute name="colEnd">   
     <xsl:value-of select="key('kEnd', 
      concat(generate-id(..), ':', generate-id()) 
     )[1]/@col" /> 
     </xsl:attribute> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

논리는 위에서 설명한 것과 정확히 같습니다. 다음과 같이

+0

답에 감사드립니다. 감사합니다. 여기에 내가 게시 한 XML 중 하나의 관심사는 실제 XML의 작은 하위 집합입니다. 우리는 약 1000 개의 행과 1000 개의 열을 기대하고 있습니다. 성능면에서 우리는 무엇을 고려해야합니까? – Gerald

+0

@Gerald : 그냥 테스트 해보십시오. 내 생각에 내 솔루션은 @ Lachlan보다 빠르고 안정적이다. 이 솔루션은 재귀를 사용하지 않으므로 "스택 오버플로"오류가 발생하지 않습니다. XSL 키를 사용하여이 솔루션을 개선하는 것에 대해 조금 생각해 볼 수 있습니다. – Tomalak

+0

@Gerald : 각 솔루션의 성능에 실제 수치를 게시 한 경우 감사하겠습니다. – Tomalak