Frage

Eine der schwierigsten Herausforderungen, die ich je im XSLT -Design gestellt habe.

So kopieren Sie die eindeutigen Zeichen in einer bestimmten Zeichenfolge.
Test XML ist:

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

Die Ausgabe, die ich erwarte, ist:

<string>aerst1234</string>
War es hilfreich?

Lösung

Hier ist eine XSLT 1.0-Lösung, kürzer als die aktuell ausgewählte Antwort und einfacher zu schreiben, da sie die STR-Foldl-Vorlage von verwendet 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>

Wenn die obige Transformation auf das ursprünglich bereitgestellte Quell -XML -Dokument angewendet wird:

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

Das gewünschte Ergebnis wird produziert:

aerst1234

Lesen Sie mehr über FXSL 1.x (für XSLT 1.0) hier, und über FXSL 2.x (für XSLT 2.0) hier.

Andere Tipps

Verwenden Sie den folgenden XPath-Ein-Liner:

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

Eine vollständige Transformation, die dies verwendet:

<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>

Wenn diese Transformation auf dem ursprünglich bereitgestellten XML -Dokument angewendet wird:

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

Das gewünschte Ergebnis wird produziert:

aerst1234

Falls eine XSLT 1.0 -Lösung benötigt wird - bitte geben Sie dies an und ich werde sie zur Verfügung stellen.

Hier ist eine XSLT 1.0 -Lösung:

<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>

Als ich es mit einem komplizierteren XML versuchte, dann traf ich viele Probleme mit Martin HonnenDie Lösung, es funktioniert nicht mit dem unten genannten XML Diese AntwortUnd ich könnte es auch eine effizientere Lösung nennen:

Hier ist ein Eingang XML:

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

Und hier ist der funktionierende XSLT -Code:

  <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>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top