문제

의문

XSLT 1.0을 사용하여 임의의 문자가있는 문자열이 주어지면 다음 규칙을 충족하는 문자열을 되 찾을 수 있습니다.

  1. 첫 번째 캐릭터는 AZ, AZ, 콜론 또는 밑줄 중 하나 여야합니다.
  2. 다른 모든 문자는 위의 또는 0-9, 기간 또는 하이픈이어야합니다.
  3. 문자가 위의 규칙을 충족하지 않으면 밑줄로 바꾸십시오.

배경

XSLT에서는 일부 속성을 요소로 변환하지만 속성에 요소 이름에서 사용할 수없는 값이 포함되어 있지 않아야합니다. 나는 예측 가능하게 변환되는 한 속성의 무결성이 이름으로 변환되는 것에 대해 크게 신경 쓰지 않습니다. 또한 보상 할 필요가 없습니다 모든 요소 이름의 유효한 문자 (무리가 있습니다).

내가 가지고 있던 문제는 공백이 들어오는 속성에 관한 것이 었습니다.이 기능은 변환 기능이 밑줄로 쉽게 변환 할 수 있습니다.

translate(@name,' ','_')

그러나 곧 슬래시를 사용하여 일부 속성을 찾은 직후에 지금도 추가해야합니다. 이것은 빨리 손을 떼지 않을 것입니다. 허용 된 캐릭터의 화이트리스트를 정의하고 허용되지 않는 문자를 밑줄로 바꾸고 싶지만 블랙리스트에서 대체하여 작업을 번역합니다.

도움이 되었습니까?

해결책

~할 수 있었다 이 작업을 수행하려면 재귀 템플릿을 작성하여 문자열의 문자를 하나씩 작업하고 테스트하고 필요한 경우 변경하십시오. 같은 것 :

<xsl:template name="normalizeName">
  <xsl:param name="name" />
  <xsl:param name="isFirst" select="true()" />
  <xsl:if test="$name != ''">
    <xsl:variable name="first" select="substring($name, 1, 1)" />
    <xsl:variable name="rest" select="substring($name, 2)" />
    <xsl:choose>
      <xsl:when test="contains('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:_', $first) or
                      (not($first) and contains('0123456789.-', $first))">
        <xsl:value-of select="$first" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:text>_</xsl:text>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:call-template name="normalizeName">
      <xsl:with-param name="name" select="$rest" />
      <xsl:with-param name="isFirst" select="false()" />
    </xsl:call-template>
  </xsl:if>
</xsl:template>

그러나 해커를 준비하면이 작업을 수행하는 방법이 짧습니다. 먼저 일부 변수를 선언합니다.

<xsl:variable name="underscores"
  select="'_______________________________________________________'" />
<xsl:variable name="initialNameChars"
  select="'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:_'" />
<xsl:variable name="nameChars"
  select="concat($initialNameChars, '0123456789.-')" />

이제이 기술은 이름을 잡고 캐릭터를 식별하는 것입니다. 그렇지 않습니다 이름의 모든 캐릭터를 대체하여 합법적입니다. ~이다 아무것도없이 합법적입니다. 당신은 이것을 할 수 있습니다 translate() 기능. 문자열에 나타나는 불법 문자 세트가 있으면 translate() 다시 기능합니다. 다음은 템플릿입니다.

<xsl:template name="normalizeName">
  <xsl:param name="name" />
  <xsl:variable name="first" select="substring($name, 1, 1)" />
  <xsl:variable name="rest" select="substring($name, 2)" />
  <xsl:variable name="illegalFirst"
    select="translate($first, $initialNameChars, '')" />
  <xsl:variable name="illegalRest"
    select="translate($rest, $nameChars, '')" />
  <xsl:value-of select="concat(translate($first, $illegalFirst, $underscores),
                               translate($rest, $illegalRest, $underscores))" />
</xsl:template>

당신이 조심해야 할 유일한 것은 밑줄 문자열이 단일 이름으로 나타날 수있는 모든 불법 문자를 다루기에 충분히 길어야한다는 것입니다. 당신이 겪을 가능성이 가장 긴 이름과 같은 길이를 만들면 트릭을 수행 할 것입니다 (아마도 훨씬 짧은 상태로 도망 칠 수 있습니다).

다른 팁

Im Ahnow Amer XSLT 1.0에는이를위한 내장이 없습니다. XSLT 2.0을 사용하면 허용됩니다 Regexes를 사용하십시오, 비록 당신의 모든 것이 그것을 알고 있다고 확신합니다.

MS Parser를 사용하는 기회가 없으면 XSLT에서 활용할 수있는 .NET Extension 라이브러리를 작성할 수 있으며 이것에 대해 썼습니다. 몇 달 전에 여기.

Saxon과 같은 것을 사용하는 경우, 그들이 자신의 확장을 코딩하는 방법을 제공하고 실제로 이미 자신의 확장을 가질 수 있지만 그 엔진에 익숙하지 않을 수도 있습니다.

도움이 되었기를 바랍니다.

또 다른 대안으로서 XSLT 표준 라이브러리에서 당신을 위해 작동 할 수있는 문자열 함수가 있습니다. http://xsltsl.sourceforge.net/string.html#template.str:string-match

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top