2017-10-25 2 views
0

입력 XML과 같은 것입니다 문자열 길이를 사용하여 속성 값을 찾아XSLT - 정규 표현식 및

<link idref="c001_r1" target="page">1</link> 
<link idref="r164">2004</link> 
<link idref="ref1">Austen et al. 1975</link> 

출력이 있어야

<link idref="c001_r1" target="literature"><sup>1</sup></link> 
<link idref="r164" target="literature">2004</link> 
<link idref="ref1" target="literature">Austen et al. 1975</link> 

우리는 아래와 같이 XSLT를 썼다.

<xsl:template match="link"> 
    <xsl:choose>    
     <xsl:when test="starts-with(@idref, 'r') and string-length(.) = 4"> 
      <xsl:copy> 
       <xsl:apply-templates select="@*"/> 
      <xsl:attribute name="target"> 
       <xsl:value-of select="'literature'" /> 
      </xsl:attribute> 
       <xsl:apply-templates select="node()"/> 
      </xsl:copy> 
     </xsl:when> 
     <xsl:when test="starts-with(@idref, 'ref') and string-length(.) > 4"> 
      <xsl:copy> 
       <xsl:apply-templates select="@*"/> 
       <xsl:attribute name="target"> 
        <xsl:value-of select="'literature'" /> 
       </xsl:attribute> 
       <xsl:apply-templates select="node()"/> 
      </xsl:copy> 
     </xsl:when> 
     <xsl:when test="contains(@idref, '(.+)_r')"> 
      <xsl:copy> 
       <xsl:apply-templates select="@*"/> 
       <xsl:attribute name="target"> 
        <xsl:value-of select="'literature'" /> 
       </xsl:attribute> 
       <sup> 
        <xsl:apply-templates select="node()"/></sup> 
      </xsl:copy> 
     </xsl:when> 
     <xsl:when test="starts-with(@idref, 'ref') and string-length(.) < 3"> 
      <xsl:copy> 
       <xsl:apply-templates select="@*"/> 
       <xsl:attribute name="target"> 
        <xsl:value-of select="'literature'" /> 
       </xsl:attribute> 
       <sup> 
       <xsl:apply-templates select="node()"/> 
       </sup> 
      </xsl:copy> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:copy> 
       <xsl:apply-templates select="@*"/> 
       <xsl:attribute name="target"><xsl:text>page</xsl:text>       
       </xsl:attribute> 
       <xsl:apply-templates select="node()"/> 
       </xsl:copy> 
     </xsl:otherwise> 
    </xsl:choose>   
</xsl:template> 

위의 xslt, 3 및 4 조건을 사용하는 동안 작동하지 않습니다. 속성 값과 문자열 길이에 따라 속성을 추가해야합니다. 스팅 길이를 계산하기 위해 (<) 부호를 언급 할 수 없습니다.

답변

1

"작동하지 않는다"고 말하는 것이 아니라 실제로 오류를 언급해야합니다. < 기호를 들어, 당신은 아마 XSL "요소 유형과 연관된"테스트 "속성의 값"의 라인을 따라 오류를 얻고있다 ". '<'문자를 포함 할 수 없습니다"

당신의 xsl:when의 구문, 당신은 XSLT 2.0 또는 다른 조건

<xsl:when test="starts-with(@idref, 'ref') and string-length(.) lt 3"> 

이상을 사용하는 경우이, 당신이 사용을이

<xsl:when test="starts-with(@idref, 'ref') and string-length(.) &lt; 3"> 

더 나은 방법이어야한다 contains이지만 정규 표현식을 지원하지 않습니다. 한 문자열이 다른 문자열의 하위 문자열인지 단순히 확인합니다. 여기에서 matches을 사용해야합니다.

<xsl:when test="matches(@idref, '.+_r.+')"> 

이렇게하려면 XSLT 2.0 이상이 필요합니다.

많은 반복 코드가 있음에 유의하십시오. 이것을 단순화 해보십시오. 예를 들면 ...

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
    <xsl:output method="xml" indent="yes" /> 

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

    <xsl:template match="link"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*"/> 
      <xsl:if test="(starts-with(@idref, 'r') and string-length(.) = 4) 
         or (starts-with(@idref, 'ref') and string-length(.) > 4) 
         or (matches(@idref, '.+_r.+')) 
         or (starts-with(@idref, 'ref') and string-length(.) lt 3)"> 
       <xsl:attribute name="target" select="'literature'" /> 
      </xsl:if> 
      <xsl:apply-templates /> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 
+0

더 많은 설명이 포함 된 귀중한 답변을 주셔서 감사합니다. 정말 도움이됩니다. – Sumathi