2016-01-12 24 views
7

O XSL akıllıca numaralarını idare edebildi fark son zamanlarda şaşırdıXSLT Strings olarak Numaraları karşılaştırın

Arkaplan; karşılaştırmaları yaparken sayısal olarak metin olarak sayıları tedavi etmeyi bilmek (yani, '10' < '7' düşüncesinden ziyade 7 < 10 olduğunu anlamış). Benim durumumda istediğim buydu; Beklediğim gibi değil. Meraktan

Sonra ama hiçbir şans ile (string() işlevini kullanarak yani dizeleri olarak sayıları karşılaştırmak XSLT'yi zorlamaya çalıştı.

Soru

o XSLT'yi almak mümkün mü dizeleri olarak sayıları karşılaştırmak; örneğin bu yüzden '10' < '7'

Örnek

Sou? rce XML:

<?xml version="1.0" encoding="utf-8"?> 
<element> 
    <x>1</x> 
    <x>2</x> 
    <x>3</x> 
    <x>4</x> 
    <x>5</x> 
    <x>6</x> 
    <x>7</x> 
    <x>8</x> 
    <x>9</x> 
    <x>10</x> 
</element> 

XSLT:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output indent="yes"/> 
    <xsl:template match="element"> 
    <element> 

     <AsItComes> 
     <xsl:for-each select="./x"> 
      <xsl:if test="./text() &lt; 7"> 
      <xsl:copy-of select="."></xsl:copy-of> 
      </xsl:if> 
     </xsl:for-each> 
     </AsItComes> 

     <AsNumber> 
     <xsl:for-each select="./x"> 
     <xsl:if test="number(./text()) &lt; 7"> 
      <xsl:copy-of select="."></xsl:copy-of> 
     </xsl:if> 
     </xsl:for-each> 
     </AsNumber> 

     <AsString> 
     <xsl:for-each select="./x"> 
      <xsl:if test="string(./text()) &lt; '7'"> 
      <xsl:copy-of select="."></xsl:copy-of> 
      </xsl:if> 
     </xsl:for-each> 
     </AsString> 

    </element> 
    </xsl:template> 
</xsl:stylesheet> 

Beklenen Çıktı:

<?xml version="1.0" encoding="utf-8"?> 
<element> 
    <AsItComes> 
    <x>1</x> 
    <x>2</x> 
    <x>3</x> 
    <x>4</x> 
    <x>5</x> 
    <x>6</x> 
    <x>10</x> 
    </AsItComes> 
    <AsNumber> 
    <x>1</x> 
    <x>2</x> 
    <x>3</x> 
    <x>4</x> 
    <x>5</x> 
    <x>6</x> 
    </AsNumber> 
    <AsString> 
    <x>1</x> 
    <x>2</x> 
    <x>3</x> 
    <x>4</x> 
    <x>5</x> 
    <x>6</x> 
    <x>10</x> 
    </AsString> 
</element> 

Gerçek Çıktı:

<?xml version="1.0" encoding="utf-8"?> 
<element> 
    <AsItComes> 
    <x>1</x> 
    <x>2</x> 
    <x>3</x> 
    <x>4</x> 
    <x>5</x> 
    <x>6</x> 
    </AsItComes> 
    <AsNumber> 
    <x>1</x> 
    <x>2</x> 
    <x>3</x> 
    <x>4</x> 
    <x>5</x> 
    <x>6</x> 
    </AsNumber> 
    <AsString> 
    <x>1</x> 
    <x>2</x> 
    <x>3</x> 
    <x>4</x> 
    <x>5</x> 
    <x>6</x> 
    </AsString> 
</element> 

cevap

4

.

https://www.w3.org/TR/xpath/#booleans ne nesnenin karşılaştırılacak

bir düğüm kümesi operatörü < = <,> = veya>, nesneler sayı hem nesne dönüştürerek karşılaştırılır ve sayıları IEEE 754'e göre karşılaştırarak. < karşılaştırması, ancak ilk sayı, ikinci sayıdan daha az ise geçerli olacaktır. XSLT'de/XPATH ile

2,0 (ve 3.0 ve 3.1), açıkça karşılaştırma dizeleri karşı gerçekleştirilen ve sayı değerlerine zorlandığını emin olmak için xs:string olarak veri türünü ayarlayabilirsiniz.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:xs="http://www.w3.org/2001/XMLSchema" 
       version="2.0"> 
<xsl:template match="element"> 
    <element> 
     <AsString> 
     <xsl:for-each select="./x"> 
      <xsl:if test="xs:string(.) &lt; xs:string('7')"> 
      <xsl:copy-of select="."></xsl:copy-of> 
      </xsl:if> 
     </xsl:for-each> 
     </AsString> 
    </element> 
</xsl:template> 
</xsl:stylesheet> 

Ama dize '7' değer karşılaştırmak yeterlidir (ayrıca, <xsl:if> ortadan kaldırmak ve bir yüklemi Filtrenizi koyabilirsiniz):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
      version="2.0"> 
<xsl:template match="element"> 
    <element> 
     <AsString> 
     <xsl:for-each select="./x[. &lt; '7']"> 
      <xsl:copy-of select="."></xsl:copy-of> 
     </xsl:for-each> 
     </AsString> 
    </element> 
</xsl:template> 
</xsl:stylesheet> 
+2

Analize katılıyorum, fakat XSLT 2.0 için '' '' '' = '= '' 2.0 '' stil sayfası ile kullanmak yeterlidir. 'İnsanların xs: string' constructor çağrılarına bir şey sarmaları gerektiğini düşündüklerinden korkuyorum. –

1

ilk sayı bir işle gidiş için ise etrafında sadece ilk poz alt dize olabilir üzerinde. Karşılaştırma gerçekleştirirken XSLT/XPATH 1.0 olarak, string() değeri hala bir sayı olarak değerlendirilir görünür

<xsl:if test="substring(./text(), 1, 1) &lt; '7'"> 

döner

<AsString> 
    <x>1</x> 
    <x>2</x> 
    <x>3</x> 
    <x>4</x> 
    <x>5</x> 
    <x>6</x> 
    <x>10</x> 
</AsString> 
+1

Teşekkürler @MartinVitek; iyi bir çözüm. Tam bir metin karşılaştırmasının mümkün olup olmadığına gerçekten ilgi duyuyorum; Gerçi herhangi bir ihtiyaç/gereksinimden ziyade sadece meraktan. – JohnLBevan

1

Not XSLT 1.0 hem 'a' > 'b' yılında ve 'b' > 'a', false olarak değerlendirmektedir.