XSLT 1.0을 사용하여 문자열에서 고유 문자를 추출하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/2264394

  •  20-09-2019
  •  | 
  •  

문제

XSLT 디자인에서 내가 직면 한 가장 어려운 도전 중 하나 ..

주어진 문자열로 고유 한 문자를 복사하는 방법 ..
테스트 XML은 다음과 같습니다.

<root>
<string>aaeerstrst11232434</string>
</root>

내가 기대하는 출력은 다음과 같습니다.

<string>aerst1234</string>
도움이 되었습니까?

해결책

다음은 XSLT 1.0 솔루션이 있습니다. fxsl.

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:f="http://fxsl.sf.net/"
 exclude-result-prefixes="f">

 <xsl:import href="str-foldl.xsl"/>
 <xsl:output method="text"/>

 <f:addUnique/>

 <xsl:variable name="vFunAddunique" select=
  "document('')/*/f:addUnique[1]
  "/>

    <xsl:template match="string">
      <xsl:call-template name="str-foldl">
        <xsl:with-param name="pFunc" select="$vFunAddunique"/>
        <xsl:with-param name="pA0" select="''"/>
        <xsl:with-param name="pStr" select="."/>
      </xsl:call-template>
    </xsl:template>

    <xsl:template match="f:addUnique" mode="f:FXSL">
      <xsl:param name="arg1"/>
      <xsl:param name="arg2"/>

      <xsl:value-of select="$arg1"/>
      <xsl:if test="not(contains($arg1, $arg2))">
       <xsl:value-of select="$arg2"/>
      </xsl:if>
    </xsl:template>
</xsl:stylesheet>

위의 변환이 원래 제공된 소스 XML 문서에 적용되는 경우:

<root>
    <string>aaeerstrst11232434</string>
</root>

원하는 결과가 생성됩니다:

aerst1234

FXSL 1.X에 대해 자세히 알아보십시오 (XSLT 1.0 용) 여기, 및 약 FXSL 2.X (XSLT 2.0 용) 여기.

다른 팁

다음 XPath One-Liner를 사용하십시오:

codepoints-to-string(distinct-values(string-to-codepoints(.)))

이것을 사용하는 완전한 변환은 다음과 같습니다:

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

    <xsl:template match="string">
      <xsl:value-of select=
      "codepoints-to-string(distinct-values(string-to-codepoints(.)))
      "/>
    </xsl:template>
</xsl:stylesheet>

이 변환이 원래 제공된 XML 문서에 적용될 때:

<root>
    <string>aaeerstrst11232434</string>
</root>

원하는 결과가 생성됩니다:

aerst1234

XSLT 1.0 솔루션이 필요한 경우 - 제발 표시하면 제공하겠습니다.

다음은 XSLT 1.0 솔루션입니다.

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

  <xsl:strip-space elements="*"/>
  <xsl:output method="text"/>

  <xsl:template match="string">
    <xsl:call-template name="unique">
      <xsl:with-param name="input" select="."/>
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="unique">
    <xsl:param name="input"/>
    <xsl:param name="output" select="''"/>
    <xsl:variable name="c" select="substring($input, 1, 1)"/>
    <xsl:choose>
      <xsl:when test="not($input)">
        <xsl:value-of select="$output"/>
      </xsl:when>
      <xsl:when test="contains($output, $c)">
        <xsl:call-template name="unique">
          <xsl:with-param name="input" select="substring($input, 2)"/>
          <xsl:with-param name="output" select="$output"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name="unique">
          <xsl:with-param name="input" select="substring($input, 2)"/>
          <xsl:with-param name="output" select="concat($output, $c)"/>
        </xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

더 복잡한 XML로 시도했을 때 많은 문제가 발생했습니다. 마틴 호넨의 솔루션은 아래에 언급 된 XML과 함께 작동하지 않으므로 Dimitre의 솔루션을 준비했습니다. 이 답변또한 더 효율적인 솔루션이라고 부를 수 있습니다.

입력 XML은 다음과 같습니다.

    <root>
      <string>aabcdbcd1abcdefghijklmanopqrstuvwxyzabcdefgh0123456789ijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz12312489796453134049446798421230156489413210315487804210313264046040489789789745648974321231564648971232344</string>
      <string2>oejrinsjfojofjweofj24798273492jfakjflsdjljk</string2>
    </root>

다음은 작동하는 XSLT 코드입니다.

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="text()">
    <xsl:call-template name="unique_chars">
      <xsl:with-param name="input" select="."/>
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="unique_chars">
    <xsl:param name="input"/>
    <xsl:variable name="c">
      <xsl:value-of select="substring($input, 1, 1)"/>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="not($input)"/>
      <xsl:otherwise>
        <xsl:choose>
          <xsl:when test="contains(substring($input, 2), $c)">
            <xsl:call-template name="unique_chars">
              <xsl:with-param name="input" select="substring($input, 2)"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$c"/>
            <xsl:call-template name="unique_chars">
              <xsl:with-param name="input" select="substring($input, 2)"/>
            </xsl:call-template>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top