2014-11-25 1 views
2

XSLT 2.0을 사용하여 텍스트 파일을 읽고 XML을 출력해야합니다.XSLT 2.0을 사용하여 텍스트 파일에서 읽을 때 상위 요소를 추가하는 방법은 무엇입니까?

Start:000,A:123,B:234,C:33,End:99,Start:03,A:123d,B:234s,End:992,Start:a00,B:234,C:33,End:99 

그리고 원하는 XML 출력은 같은 것입니다 : 입력 텍스트 파일과 같은 것입니다

<File> 
<Rec> 
    <Start>000</Start> 
    <A>123</A> 
    <B>234</B> 
    <C>33</C> 
    <End>99</End> 
</Rec> 
<Rec> 
    <Start>03</Start> 
    <A>123d</A> 
    <B>234s</B> 
    <End>992</End> 
</Rec> 
<Rec> 
    <Start>a00</Start> 
    <B>234</B> 
    <C>33</C> 
    <End>99</End> 
</Rec> 

내가 어려움 "끝"에서 "시작"의 요소를 그룹화하고 부모를 추가하는이 엘리먼트 "Rec". 어떠한 제안? 고마워요!

+0

XSLT는 XML 문서를 변형하고 있습니다. 실제로 구조화되지 않은 평범한 텍스트 파일을 다루는 올바른 도구는 아닙니다. 작은 스크립트 (Python, Perl, 심지어 bash ... 당신이 편하게 느끼는 것)로 더 나을 것입니다. – xbug

+2

@xbug - 공정한 진술이지만,이 질문 에서처럼 간단한 변형 인 경우 XSLT가 좋습니다. 특히 결과 XML이 더욱 변형 될 때. 파싱되지 않은 텍스트를 XML로 변환하고 변형에 저장할 변수에 저장하는 것이 편리 할 때도 있습니다. 그렇지 않으면 기술을 혼합해야합니다 (항상 나쁜 것은 아니며, 특히 다른 언어를 사용하여 XSLT를 실행하는 경우). –

+0

@xbug - XSLT 2.0은 다른 언어와 마찬가지로 이러한 종류의 작업을 처리합니다. –

답변

3

찾고 싶은 출력을 만들려면 unparsed-text()tokenize()을 사용할 수 있습니다. 텍스트 파일에 둘 이상의 행이있을 경우 xsl:analyze-string을 사용할 수도 있습니다.

예 ...

텍스트 입력 (so.txt)

Start:000,A:123,B:234,C:33,End:99,Start:03,A:123d,B:234s,End:992,Start:a00,B:234,C:33,End:99 

XSLT 2.0

<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:strip-space elements="*"/> 

    <xsl:param name="input-encoding" as="xs:string" select="'iso-8859-1'"/> 
    <xsl:param name="input-uri" as="xs:string" select="'so.txt'"/> 

    <xsl:template match="/"> 
     <xsl:variable name="input" select="unparsed-text($input-uri, $input-encoding)"/> 
     <File> 
      <xsl:analyze-string select="$input" regex="\r\n?|\n"> 
       <xsl:non-matching-substring> 
        <xsl:for-each select="tokenize(.,'Start')[string()]"> 
         <Rec> 
          <xsl:for-each select="tokenize(.,',')[string()]"> 
           <xsl:variable name="vals" select="tokenize(.,':')"/> 
           <xsl:element name="{if (position()=1) then 'Start' else $vals[1]}"> 
            <xsl:value-of select="$vals[2]"/> 
           </xsl:element> 
          </xsl:for-each>        
         </Rec> 
        </xsl:for-each> 
       </xsl:non-matching-substring> 
      </xsl:analyze-string> 
     </File> 
    </xsl:template> 

</xsl:stylesheet> 

XML 출력

<File> 
    <Rec> 
     <Start>000</Start> 
     <A>123</A> 
     <B>234</B> 
     <C>33</C> 
     <End>99</End> 
    </Rec> 
    <Rec> 
     <Start>03</Start> 
     <A>123d</A> 
     <B>234s</B> 
     <End>992</End> 
    </Rec> 
    <Rec> 
     <Start>a00</Start> 
     <B>234</B> 
     <C>33</C> 
     <End>99</End> 
    </Rec> 
</File> 
+0

+ 1은 거의 사용하지 않는 XSLT 기능을 잘 사용합니다. –

+0

마스터, 당신의 논리에 모자. +1 –

0

토큰 화 한 다음 그룹화하면됩니다.

<xsl:variable name="raw" as="element()*"> 
    <xsl:for-each select="tokenize(normalize-space(unparsed-text('input.txt')), ',')"> 
    <xsl:element name="{substring-before(., ':')}"> 
     <xsl:value-of select="substring-after(., ':')"/> 
    </xsl:element> 
    </xsl:for-each> 
</xsl:variable> 
<File> 
    <xsl:for-each-group select="$raw" group-starting-with="Start"> 
    <Rec> 
     <xsl:copy-of select="current-group()"/> 
    </Rec> 
    </xsl:for-each-group> 
</File>