2014-01-29 2 views
1

XML 파일을 처리하려고합니다. 특정 특성이있는 일부 요소는 새 요소의 하위 요소 여야합니다. 일치하지 않는 요소의 다른 형제도 거기에 그대로 있어야합니다. 좋은 예가 될 것입니다.일치하는 요소를 그대로 새 요소에 추가합니다.

일치시키려는 토큰의 속성은 id = 't_15'이고 id는 't_16'입니다.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="1.0"> 
    <xsl:output omit-xml-declaration="yes" indent="no"></xsl:output> 

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

    <xsl:variable name="dif_tok"> 
     <dif_tok>t_15</dif_tok> 
     <dif_tok>t_16</dif_tok> 
    </xsl:variable> 

    <xsl:template match="s"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*"></xsl:apply-templates> 
      <e> 
       <xsl:copy-of select="*[@id = $dif_tok/dif_tok]"></xsl:copy-of> 
      </e> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

:

<text> 
    <div id="d_1"> 
    <p id="p_1"> 
     <s id="s_1"> 
     <token id="t_13" lemma="colleague" pos="NN">Colleagues</token> 
     <token id="t_14" lemma="," pos=",">,</token> 
     <e> 
      <token id="t_15" lemma="we" pos="PP">we</token> 
      <token id="t_16" lemma="now" pos="RB">now</token> 
     </e> 
     <token id="t_17" lemma="come" pos="VVP">come</token> 
     <token id="t_18" lemma="to" pos="TO">to</token> 
     <token id="t_19" lemma="catch-the-eye" pos="NN">catch-the-eye</token> 
     <token id="t_20" lemma="." pos="SENT">.</token> 
     </s> 
     <s id="s_2"> 
     <token id="t_21" lemma="these" pos="DT">These</token> 
     <token id="t_22" lemma="be" pos="VBP">are</token> 
     <token id="t_23" lemma="the" pos="DT">the</token> 
     <token id="t_24" lemma="name" pos="NNS">names</token> 
     <token id="t_25" lemma="I" pos="PP">I</token> 
     <token id="t_26" lemma="will" pos="MD">will</token> 
     <token id="t_27" lemma="call" pos="VV">call</token> 
     <token id="t_28" lemma="out" pos="RP">out</token> 
     <token id="t_29" lemma="." pos="SENT">.</token> 
     </s> 
    </p> 
    </div> 
</text> 

이것은 내가 사용하고있는 스타일입니다 :

<text> 
    <div id="d_1"> 
    <p id="p_1"> 
     <s id="s_1"> 
     <token id="t_13" lemma="colleague" pos="NN">Colleagues</token> 
     <token id="t_14" lemma="," pos=",">,</token> 
     <token id="t_15" lemma="we" pos="PP">we</token> 
     <token id="t_16" lemma="now" pos="RB">now</token> 
     <token id="t_17" lemma="come" pos="VVP">come</token> 
     <token id="t_18" lemma="to" pos="TO">to</token> 
     <token id="t_19" lemma="catch-the-eye" pos="NN">catch-the-eye</token> 
     <token id="t_20" lemma="." pos="SENT">.</token> 
     </s> 
     <s id="s_2"> 
     <token id="t_21" lemma="these" pos="DT">These</token> 
     <token id="t_22" lemma="be" pos="VBP">are</token> 
     <token id="t_23" lemma="the" pos="DT">the</token> 
     <token id="t_24" lemma="name" pos="NNS">names</token> 
     <token id="t_25" lemma="I" pos="PP">I</token> 
     <token id="t_26" lemma="will" pos="MD">will</token> 
     <token id="t_27" lemma="call" pos="VV">call</token> 
     <token id="t_28" lemma="out" pos="RP">out</token> 
     <token id="t_29" lemma="." pos="SENT">.</token> 
     </s> 
    </p> 
    </div> 
</text> 

이 내가 좀하고 싶습니다 출력은 다음과 같습니다

는 입력 XML이다 그리고 이것이 마침내 내가 얻는 결과입니다 :

특정 속성개
<text> 
    <div id="d_1"> 
    <p id="p_1"> 
     <s id="s_1"><e><token id="t_15" lemma="we" pos="PP">we</token><token id="t_16" lemma="now" pos="RB">now</token></e></s> 
     <s id="s_2"><e/></s> 
    </p> 
    </div> 
</text> 
+0

죄송 합니다만 원래 게시물에서는 XSLT 2.0 선언을 사용했지만 (방금 편집했습니다). 나는 XSLT 1.0 솔루션을 선호한다. XSLT 1.0 만 지원하는 lxml을 사용하여 파이썬 스크립트에 통합하고 싶습니다. –

+0

Ian의 솔루션을 사용해 보았습니다. 정확히 찾고자하지만 XSLT 2.0입니다. 이제, 나는 그의 제안을 더 이상 볼 수 없지만 그것은 아주 좋았다. –

+0

다음번에 뭔가를 물어 보면 올바른 버전을 사용하고 있는지 확인하십시오. 이것은 내가 말하기에 상당히 성가신 일이다. –

답변

0

일부 요소는

당신이 관심있는 token 요소에 맞게 별도의 템플릿을 쓰기 새로운 요소의 자식이어야합니다. 템플릿 내부

<xsl:template match="token[@id ='t_15']"> 

e 요소를 생성하고 apply-templates의 동작을 활용하여 토큰으로 채 웁니다. 여기서 @id = t_15 and t_16입니다. 그런 다음, 항등 변환을 나머지 모든 일을하게하십시오.

스타일 시트

<?xml version="1.0" encoding="utf-8"?> 

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

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

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

    <xsl:template match="token[@id ='t_15']"> 
     <e> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
     <xsl:apply-templates select="following-sibling::token[1]"/> 
     </e> 
    </xsl:template> 

</xsl:stylesheet> 

출력

<?xml version="1.0" encoding="UTF-8"?> 
<text> 
    <div id="d_1"> 
     <p id="p_1"> 
     <s id="s_1"> 
      <token id="t_13" lemma="colleague" pos="NN">Colleagues</token> 
      <token id="t_14" lemma="," pos=",">,</token> 
      <e> 
       <token id="t_15" lemma="we" pos="PP">we</token> 
       <token id="t_16" lemma="now" pos="RB">now</token> 
      </e> 
      <token id="t_16" lemma="now" pos="RB">now</token> 
      <token id="t_17" lemma="come" pos="VVP">come</token> 
      <token id="t_18" lemma="to" pos="TO">to</token> 
      <token id="t_19" lemma="catch-the-eye" pos="NN">catch-the-eye</token> 
      <token id="t_20" lemma="." pos="SENT">.</token> 
     </s> 
     <s id="s_2"> 
      <token id="t_21" lemma="these" pos="DT">These</token> 
      <token id="t_22" lemma="be" pos="VBP">are</token> 
      <token id="t_23" lemma="the" pos="DT">the</token> 
      <token id="t_24" lemma="name" pos="NNS">names</token> 
      <token id="t_25" lemma="I" pos="PP">I</token> 
      <token id="t_26" lemma="will" pos="MD">will</token> 
      <token id="t_27" lemma="call" pos="VV">call</token> 
      <token id="t_28" lemma="out" pos="RP">out</token> 
      <token id="t_29" lemma="." pos="SENT">.</token> 
     </s> 
     </p> 
    </div> 
</text> 

당신의 시도 솔루션은 변수를 사용합니다. 이것은 좋은 접근 방식입니다.

<xsl:variable name="start" select="'t_15'"/> 

<xsl:template match="token[@id=$start]"> 
    <e> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    <xsl:apply-templates select="following-sibling::token[1]"/> 
    </e> 
</xsl:template> 
+0

감사합니다. Matthias! 좀 더 유연하게하기 위해서 내가 물어 보도록하겠습니다 : 요소 ''에 추가하고자하는 토큰의 범위는 1 토큰 또는 n 토큰의 토큰을 가질 수 있습니다. 어떻게 할 건데? 스타일 시트에 첫 번째 토큰 ID와 처리 될 토큰 길이 또는 마지막 토큰의 ID가있는 매개 변수를 전달할 수 있습니다. t_15 및 t_16 대신 t_15 또는 t_15, t_16, t_17 만 처리하려고했습니다. 베스트! –

+0

' now'이 출력에 두 번 나타났습니다. –

+0

@ JoelM.Lamsen : 좋은 지적입니다. 이것은별로 좋지 않은 부작용입니다. –

0

나는 Mathias가 만든 스타일 시트를 약간 수정했습니다. 아래를 참조하십시오.

<?xml version="1.0" encoding="utf-8"?> 

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

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

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

    <xsl:variable name="start" select="'t_15'"/> 
    <xsl:variable name="middle" select="'t_16'"/> 
    <xsl:variable name="end" select="'t_17'"/> 

    <xsl:template match="token[@id =$start]"> 
     <e> 
      <xsl:copy> 
       <xsl:apply-templates select="@*|node()"/> 
      </xsl:copy> 
      <xsl:apply-templates select="following-sibling::token[@id=$middle]" mode="group"/> 
      <xsl:apply-templates select="following-sibling::token[@id=$end]" mode="group"/> 
     </e> 
    </xsl:template> 

    <xsl:template match="token[@id =$middle]|token[@id =$end]" mode="group"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="token[@id =$middle]|token[@id =$end]"/> 

</xsl:stylesheet> 
0

편집 :이 답변을 작성한 이래로 2.0보다는 XSLT 1.0을 요구하는 질문이 변경되었지만 여기서 답을 남겨 두겠습니다. 당신이 XSLT 2.0에있어 이후


for-each-groupgroup-adjacent 메커니즘에 대한 이상적인 경우입니다.당신은 누구의 식별자 $tokensToGroup 일치 부울 truecurrent-grouping-key() 값을 하나의 그룹으로 수집됩니다

<xsl:variable name="tokensToGroup" select="('t_15', 't_16')" /> 

<xsl:template match="s"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*" /> 
    <xsl:for-each-group select="token" group-adjacent="@id = $tokensToGroup"> 
     <xsl:choose> 
     <xsl:when test="current-grouping-key()"> 
      <e><xsl:apply-templates select="current-group()" /></e> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:apply-templates select="current-group()" /> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:for-each-group> 
    </xsl:copy> 
</xsl:template> 

에 대한 인접 토큰이 다른 토큰은 키 그룹으로 수집되는 방법을 다음, 이전과 정체성 서식을 가정 false - true 키를 사용하여 <e>...</e> 만 감쌀 수 있습니다. 대신에 그룹의 모든 ID의 목록으로, 당신은 단지 첫 번째와 마지막 토큰의 ID가있는 경우

, 당신은 동일한 메커니즘을 사용할 수 있지만 여기에 다른 그룹화 키 정의와

<xsl:param name="first" select="'t_15'" /> 
<xsl:param name="last" select="'t_17'" /> 

<xsl:for-each-group select="token" 
    group-adjacent="((. | preceding-sibling::token)[@id = $first] and 
        (. | following-sibling::token)[@id = $last])"> 

true 키 값은 $lastToken 또는 그 이전 또는 이후의 $firstToken 또는 그 이후의 요소에 대한 값입니다. 이것은 프로세서가 키를 최적화하지 않았다고 가정 할 때 키를 사용하면 좀 더 효율적일 수 있습니다.

<xsl:key name="tokenById" match="token" use="@id" /> 

<xsl:variable name="firstToken" select="key('tokenById', $first)" /> 
<xsl:variable name="lastToken" select="key('tokenById', $last)" /> 

<xsl:for-each-group select="token" 
    group-adjacent="((. is $firstToken or . &gt;&gt; $firstToken) and 
        (. is $lastToken or . &lt;&lt; $lastToken))"> 
관련 문제