可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
<Description>this is my value 822880494 this is my value</Description>
I'm quite new to xpath, xml and stylevision so this might be a basic problem.
I am using stylevision 2010 and xpath to create an sps/xslt for an schema.
In the above node you can see there is a numeric value inside the node and I want to extract that value and turn it into a link in my pdf/html. The problem is that i cant seem to extract it. Substring is not an option since the length of the value and the position of the numeric value inside it varies.
Some will probably think that the schema is badly composed and that the numeric value should be in a seperate node/attribute/... There is nothing I can do about that since this schema is provided by another company.
Thanks in advance!
回答1:
StyleVision 2010 seems to support XSLT 2.0, so you could use a 2.0 stylesheet and do something like
<xsl:analyze-string select='$foo' regex='\d+'>
<xsl:matching-substring>
<number><xsl:value-of select='.' /></number>
</xsl:matching-substring>
</xsl:analyze-string>
Or whatever you want to do with the number; the string with the number is the context element inside the <xsl:matching-substring>
element.
Newtover's translate
idea (for XSLT 1.0) would look like this:
<xsl:value-of select="translate(., translate(., '0123456789', ''), '')" />
But if your input contains multiple numbers, that will simply concatenate them.
回答2:
Use this simple XPath 1.0 expression:
translate(.,translate(., '0123456789', ''), '')
Here is a complete XSLT 1.0 solution:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:value-of select=
"translate(.,translate(., '0123456789', ''), '')"/>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on the provided XML document:
<Description>this is my value 822880494 this is my value</Description>
the wanted, correct result is produced:
822880494
Explanation:
This is known as the Double Translate Method first proposed by Michael Kay. It consists of two nested calls to the translate()
function:
Inner translate()
. This produces all characters of the string, except digits.
Outer translate()
. This deletes from the string all characters produced by the inner translate()
. What remains is just the wanted characters (the digits).
回答3:
A fragile but possible solution in plain XSLT 1.0 would be to use a composition of translate
(to make all non-numeric values to empty strings or spaces) and normalize-space
(to trim the rest of spaces, though translate
might suffice). This will certainly work only if there are no other numeric values within the string. And, I can't currently check, translate
might work only if your string contains ascii characters.
XSLT 2.0 has several regexp functions. If you xslt processor allows using EXSLT extentions, it as well contains regexp functions, or you can tokenize your string by spaces and provide non-empty template to the numeric token only.
p.s. I am sorry, that I do not provide any links, it's hard to to from the device.
回答4:
hi this will produce the results you requre! it checks each character, and then makes sure that it is a number.
XSLT 1 Solution
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Root/Description">
<xsl:call-template name="for-each-character">
<xsl:with-param name="data" select="."/>
</xsl:call-template>
</xsl:template>
<xsl:template name="for-each-character">
<xsl:param name="data"/>
<xsl:if test="string-length($data) > 0">
<xsl:if test="substring($data,1,1)>-1">
<xsl:value-of select="substring($data,1,1)"/>
</xsl:if>
<xsl:call-template name="for-each-character">
<xsl:with-param name="data" select="substring($data,2)"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
回答5:
The following is a derivation of the above XSLT v1 solution, however, this is specifically for a leading number, as versus embedded in the middle of the string. It also allows for floating point or integer parsing. (I personally find this useful for breaking apart units from values, such as "80 mg" or "128.4 mm2", where the unit is "mm2", and the value "128.4" , and NOT "128.42".
<xsl:template name="parseNumber">
<xsl:param name="data"/>
<xsl:param name="is-float" select="false()"/><!-- has this already been determined to be a non-integer -->
<xsl:if test="string-length($data) > 0">
<xsl:if test="(substring($data,1,1)>-1) or ((substring($data,1,1) = '.') and (not($is-float)) )">
<xsl:value-of select="substring($data,1,1)"/>
<xsl:call-template name="parseNumber">
<xsl:with-param name="data" select="substring($data,2)"/>
<xsl:with-param name="is-float" select="(substring($data,1,1) = '.') or ($is-float)"/>
</xsl:call-template>
</xsl:if>
</xsl:if>
</xsl:template>
The following are some unit-test cases with comparative results:
Test: [123] ?=? numer(): [123] ?=? for-each-char: [123] ?=? parseNumber: [123]
Test: [1.23] ?=? numer(): [1.23] ?=? for-each-char: [1.23] ?=? parseNumber: [1.23]
Test: [1.1.1.1] ?=? numer(): [NaN] ?=? for-each-char: [1.1.1.1] ?=? parseNumber: [1.1]
Test: [123 abc] ?=? numer(): [NaN] ?=? for-each-char: [123] ?=? parseNumber: [123]
Test: [123 abc2] ?=? numer(): [NaN] ?=? for-each-char: [1232] ?=? parseNumber: [123]
Test: [123.456 abc7] ?=? numer(): [NaN] ?=? for-each-char: [123.4567] ?=? parseNumber: [123.456]
Test: [abc def ] ?=? numer(): [NaN] ?=? for-each-char: [] ?=? parseNumber: []
Test: [abc 123] ?=? numer(): [NaN] ?=? for-each-char: [123] ?=? parseNumber: []