/ / Ako nahradiť viac skratiek adries v reťazci adresy pomocou XSLT 2.0 - xml, xslt, xslt-2.0

Ako nahradiť viac skratiek adries v reťazci adries pomocou XSLT 2.0 - xml, xslt, xslt-2.0

Dané: XSLT 2.0; Saxon EE 9.6.0.4

Zdroj XML:

<clients>
<client id="1">
<address>12345 Elm Dr</address>
</client>
<client id="2">
<address>12345 Elm Cr</address>
</client>
</clients>

Potrebujem urobiť nejaké porovnanie adries, aby som našiel zhody, kde jedna adresa môže používať skratku a adresa, ktorú porovnávam, nemusí. Tu je niekoľko príkladov, čo mám na mysli:

Ave = Avenue
Blvd = Boulevard
Cir = Circle
Ct = Court
Dr = Drive
Hwy = Highway

Hľadaná adresa sa odovzdá do šablóny štýlov ako parameter, takže povedzme, že táto adresa bola odovzdaná do nasledujúcej ukážky šablóny so štýlmi:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:param name="searchAddr">12345 Elm Drive</xsl:param>
<xsl:variable name="punctuation">
<xsl:text> .!@#$%^*()_+{}[]|`:;?,*-=/</xsl:text>
</xsl:variable>
<xsl:template match="/">
<xsl:for-each select="clients/client[address[upper-case(translate(.,$punctuation,"")) = upper-case(translate($searchAddr,$punctuation,""))]]">
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

POZNÁMKA: - Už používam preklad () na odstránenie všetkých interpunkčných znakov a veľkých písmen () na kontrolu veľkých písmen v porovnaní.

--Nemusím natrvalo vymieňať reťazce na výstupe, stačí ich vymeniť iba pre porovnanie.

--Uvedomujeme si, že toto nie je 100% spoľahlivá metóda párovania adries, ale v takom prípade to nemusíme byť ... len chceme získať ovocie s nízkou viskozitou.

Myslím si, že existuje lepší spôsob, ako to urobiť, ako 20 vnorených funkcií nahradenia alebo volanie šablóny, ktorá by prechádzala každou skratkou. Nápady?

odpovede:

2 pre odpoveď č. 1

Neviem, či existuje elegantnejší spôsob ako nahradenie operáciami vnorenia / zreťazenia. Myslím si, že nejestvujú iba rôzne spôsoby vyjadrenia tejto operácie.

A čo tak pokračovať v živote:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*" />

<xsl:param name="searchAddr">12345 Elm Drive</xsl:param>

<xsl:key name="sanitized-adresses" match="client" use="
replace(
replace(
replace(
replace(
replace(
replace(
replace(
upper-case(normalize-space(address))
,"p{P}", "")
,"(^|W)AVE($|W)", "$1AVENUE$2")
,"(^|W)DR($|W)", "$1DRIVE$2")
,"(^|W)BLVD($|W)", "$1BOULEVARD$2")
,"(^|W)CI?R($|W)", "$1CIRCLE$2")
,"(^|W)CT($|W)", "$1COURT$2")
,"(^|W)HWY($|W)", "$1HIGHWAY$2")
" />

<xsl:template match="/">
<xsl:copy-of select="key("sanitized-adresses", upper-case($searchAddr))" />
</xsl:template>
</xsl:stylesheet>

Poznámky:

  • Na p{P} je trieda znakov Unicode, ktorá zodpovedá všetkým interpunkčným znamienkam.
  • Regulárne výrazy XSLT 2.0 preto nemajú hranice slov (^|W) a ($|W) sú náhradami za b.
  • Nemá tiež pozretia alebo pozretia, preto potrebujeme $1 a $2 v náhradnom reťazci.
  • Bol som súčasťou normalize-space() vyhnúť sa problémom s medzerami
  • Na <xsl:key> nie je nevyhnutne potrebné, pridal som ju, aby sa hlavná šablóna príjemnejšie pozerala.

Ak chcete, vytvorte si <xsl:function> ktorá robí sanitáciu adresy, týmto spôsobom ho môžete znova použiť na sanitáciu parametra, čo uľahčí celkové použitie.


2 pre odpoveď č. 2

Môžete zvážiť definovanie mapovania od skratiek k reťazcom, napríklad ako parameter

<xsl:param name="mapping">
<map from="Ave" to="Avenue"/>
<map from="Blvd" to="Boulevard"/>
<map from="Dr" to="Drive"/>
</xsl:param>

a potom ste mohli vybrať

    <xsl:copy-of select="clients/client[matches(address, concat("^", $searchAddr, "$")) or (some $map in $mapping/map satisfies matches(replace(address, $map/@from, $map/@to), concat("^", $searchAddr, "$")))]"/>