[英]XSLT space separated and adding an element
I have a query in the xml and xslt 我在xml和xslt中有一个查询
The below is the Input XML 以下是输入XML
<?xml version="1.0" encoding="UTF-8"?>
<Employer>
<Employees>
<EmployeesDetails>van ind 26%</EmployeesDetails>
</Employees>
<Employees>
<EmployeesDetails>van ind</EmployeesDetails>
</Employees>
</Employer>
The above is my input file 以上是我的输入文件
the below is my output file 以下是我的输出文件
<?xml version="1.0" encoding="UTF-8"?>
<Employer>
<Employees>
<Names>van</Names>
<Location>ind</Location>
<Weather>26</Weather>
</Employees>
<Employees>
<Names>van</Names>
<Location>ind</Location>
<Weather>100</Weather>
</Employees>
</Employer>
How can I apply the below XSLT to the above XML input? 如何将下面的XSLT应用于上面的XML输入?
I. This XSLT 2.0 transformation: I.此XSLT 2.0转换:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<Employer>
<xsl:apply-templates/>
</Employer>
</xsl:template>
<xsl:template match="Employees">
<xsl:variable name="vNames" select="tokenize(Names, ' ')"/>
<xsl:variable name="vLoc" select="tokenize(Location, ' ')"/>
<xsl:variable name="vWeather"
select="tokenize(translate(Weather, '%', ' '), ' ')"/>
<xsl:for-each select="$vNames">
<xsl:variable name="vPos" select="position()" as="xs:integer"/>
<Employees>
<Names><xsl:sequence select="."/></Names>
<Location>
<xsl:sequence select="(lower-case($vLoc[$vPos]), 'Unknown')[1]"/>
</Location>
<Weather>
<xsl:sequence select="($vWeather[$vPos], 100)[1]"/>
</Weather>
</Employees>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document: 当应用于提供的XML文档时:
<Employer>
<Employees>
<Names>vel bel sel tel mel</Names>
<Location>IND AUS ENG CAL JAP</Location>
<Weather>26%</Weather>
</Employees>
<Employees>
<Names>asd sadl asdsel tdddel dmdel</Names>
<Location>IND AUS ENG CAL JAP</Location>
</Employees>
</Employer>
produces the wanted, correct result: 产生想要的正确结果:
<Employer>
<Employees>
<Names>vel</Names>
<Location>ind</Location>
<Weather>26</Weather>
</Employees>
<Employees>
<Names>bel</Names>
<Location>aus</Location>
<Weather>100</Weather>
</Employees>
<Employees>
<Names>sel</Names>
<Location>eng</Location>
<Weather>100</Weather>
</Employees>
<Employees>
<Names>tel</Names>
<Location>cal</Location>
<Weather>100</Weather>
</Employees>
<Employees>
<Names>mel</Names>
<Location>jap</Location>
<Weather>100</Weather>
</Employees>
<Employees>
<Names>asd</Names>
<Location>ind</Location>
<Weather>100</Weather>
</Employees>
<Employees>
<Names>sadl</Names>
<Location>aus</Location>
<Weather>100</Weather>
</Employees>
<Employees>
<Names>asdsel</Names>
<Location>eng</Location>
<Weather>100</Weather>
</Employees>
<Employees>
<Names>tdddel</Names>
<Location>cal</Location>
<Weather>100</Weather>
</Employees>
<Employees>
<Names>dmdel</Names>
<Location>jap</Location>
<Weather>100</Weather>
</Employees>
</Employer>
Do note : 注意事项 :
I have made the following reasonable assumptions: 我做了以下合理的假设:
You actually want 100
, not 100%
. 实际上,你想
100
,而不是100%
You want all Employees
processed -- not only the first occurence of this element. 您希望所有
Employees
处理-不仅是此元素的第一次出现。
I also added a default value for any missing location, in case the number of provided locations is less than the number of the provided names. 我还为缺少的位置添加了默认值,以防提供的位置数少于提供的名称数。
II. 二。 XSLT 1.0 solution :
XSLT 1.0解决方案 :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common"
xmlns:my="my:my" exclude-result-prefixes="ext my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<my:defaults>
<L>Unknown</L>
<W>100</W>
</my:defaults>
<xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="vDefaults" select="document('')/*/my:defaults"/>
<xsl:template match="/*">
<Employer>
<xsl:apply-templates/>
</Employer>
</xsl:template>
<xsl:template match="Employees">
<xsl:variable name="vrtfNames">
<xsl:apply-templates select="Names"/>
</xsl:variable>
<xsl:variable name="vNames" select="ext:node-set($vrtfNames)/*"/>
<xsl:variable name="vrtfLocs">
<xsl:apply-templates select="Location"/>
</xsl:variable>
<xsl:variable name="vrtfWeather">
<xsl:apply-templates select="Weather"/>
</xsl:variable>
<xsl:apply-templates select="$vNames">
<xsl:with-param name="pLocs" select="ext:node-set($vrtfLocs)/*"/>
<xsl:with-param name="pWeather" select="ext:node-set($vrtfWeather)/*"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="s" priority="3">
<xsl:param name="pLocs"/>
<xsl:param name="pWeather"/>
<xsl:variable name="vPos" select="position()"/>
<Employees>
<Names><xsl:value-of select="."/></Names>
<Location>
<xsl:value-of select=
"translate($pLocs[position() = $vPos]
| $vDefaults[not($pLocs[position() = $vPos])]/L,
$vUpper, $vLower)"/>
</Location>
<Weather>
<xsl:value-of select=
"$pWeather[position() = $vPos]
| $vDefaults[not($pWeather[position() = $vPos])]/W"/>
</Weather>
</Employees>
</xsl:template>
<xsl:template match="Weather">
<xsl:call-template name="tokenize">
<xsl:with-param name="pText" select="translate(., '%', ' ')"/>
</xsl:call-template>
</xsl:template>
<xsl:template match="Employees/*/text()" name="tokenize">
<xsl:param name="pText" select="."/>
<xsl:variable name="vText" select="normalize-space($pText)"/>
<xsl:if test="$vText">
<s>
<xsl:value-of select="substring-before(concat($vText, ' '), ' ')"/>
</s>
<xsl:call-template name="tokenize">
<xsl:with-param name="pText" select="substring-after($vText, ' ')"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document (above), again the same wanted, correct result is produced : 当此转换应用于提供的XML文档(如上)时,同样会产生所需的正确结果 :
<Employer>
<Employees>
<Names>vel</Names>
<Location>ind</Location>
<Weather>26</Weather>
</Employees>
<Employees>
<Names>bel</Names>
<Location>aus</Location>
<Weather>100</Weather>
</Employees>
<Employees>
<Names>sel</Names>
<Location>eng</Location>
<Weather>100</Weather>
</Employees>
<Employees>
<Names>tel</Names>
<Location>cal</Location>
<Weather>100</Weather>
</Employees>
<Employees>
<Names>mel</Names>
<Location>jap</Location>
<Weather>100</Weather>
</Employees>
<Employees>
<Names>asd</Names>
<Location>ind</Location>
<Weather>100</Weather>
</Employees>
<Employees>
<Names>sadl</Names>
<Location>aus</Location>
<Weather>100</Weather>
</Employees>
<Employees>
<Names>asdsel</Names>
<Location>eng</Location>
<Weather>100</Weather>
</Employees>
<Employees>
<Names>tdddel</Names>
<Location>cal</Location>
<Weather>100</Weather>
</Employees>
<Employees>
<Names>dmdel</Names>
<Location>jap</Location>
<Weather>100</Weather>
</Employees>
</Employer>
Do note : 注意事项 :
Essentially the same logic as in the XSLT 2.0 transformation is implemented. 基本上实现了与XSLT 2.0转换相同的逻辑。
As XPath 1.0 doesn't have a tokenize
or lower-case()
functions and there are is no notion of sequence in the XPath 1.0 data model, these are implemented (respectively) using a template for tokenization, using the translate()
function to convert to lower case, and using an element that contains the defaults for weather and location. 由于XPath 1.0没有
tokenize
或lower-case()
函数,并且在XPath 1.0数据模型中没有序列的概念,因此这些(分别)是使用tokenize
模板来实现的,使用translate()
函数可以转换为小写字母,并使用包含天气和位置默认值的元素。
Your question is vague in some key areas. 您的问题在某些关键领域含糊不清。 For instance, you seem to state that if a
<Employees>
nodeset doesn't have a <weather>
node, it should get one with a value of 100%; 例如,您似乎声明,如果
<Employees>
节点集没有 <weather>
节点,则它应该得到一个值为100%的节点集; that said, your expected output seems to apply that logic inconsistently. 也就是说,您的预期输出似乎不一致地应用了该逻辑。 Your desired
<Location>
result node is transformed from uppercase to lowercase. 您所需的
<Location>
结果节点将从大写转换为小写。 Additionally, your output seems to completely disregard the second <Employees>
node-set from the source XML. 此外,您的输出似乎完全忽略了源XML中的第二个
<Employees>
节点集。
Making some assumptions, here is an XSLT 1.0 solution that uses EXSLT . 进行一些假设,这是使用EXSLT的XSLT 1.0解决方案。 Should this not be what you want, please update your question to be more specific and I will try to accommodate.
如果这不是您想要的,请更新您的问题以更具体,我将尽力解决。
When this XSLT: 当此XSLT:
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:exsl="http://exslt.org/common"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="exsl"
version="1.0">
<xsl:output omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Employees">
<xsl:variable name="vNames">
<xsl:call-template name="tokenize">
<xsl:with-param name="text" select="Names/text()"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vLocations">
<xsl:call-template name="tokenize">
<xsl:with-param name="text" select="Location/text()"/>
</xsl:call-template>
</xsl:variable>
<xsl:apply-templates select="exsl:node-set($vNames)/token">
<xsl:with-param name="pLocation"
select="exsl:node-set($vLocations)/token"/>
<xsl:with-param name="pWeather" select="Weather"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="token">
<xsl:param name="pLocation"/>
<xsl:param name="pWeather"/>
<xsl:variable name="vPosition" select="position()"/>
<Employees>
<Names>
<xsl:value-of select="."/>
</Names>
<Location>
<xsl:value-of select="translate($pLocation[$vPosition],
'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
</Location>
<xsl:choose>
<xsl:when test="$pWeather != ''">
<xsl:apply-templates select="$pWeather"/>
</xsl:when>
<xsl:otherwise>
<Weather>100%</Weather>
</xsl:otherwise>
</xsl:choose>
</Employees>
</xsl:template>
<xsl:template name="tokenize">
<xsl:param name="text"/>
<xsl:param name="delimiter" select="' '"/>
<xsl:choose>
<xsl:when test="contains($text,$delimiter)">
<xsl:element name="token">
<xsl:value-of select="substring-before($text,$delimiter)"/>
</xsl:element>
<xsl:call-template name="tokenize">
<xsl:with-param name="text"
select="substring-after($text,$delimiter)"/>
<xsl:with-param name="delimiter" select="$delimiter"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="$text">
<xsl:element name="token">
<xsl:value-of select="$text"/>
</xsl:element>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
...is applied to this XML: ...应用于此XML:
<?xml version="1.0"?>
<Employer>
<Employees>
<Names>vel bel sel tel mel</Names>
<Location>IND AUS ENG CAL JAP</Location>
<Weather>26%</Weather>
</Employees>
<Employees>
<Names>asd sadl asdsel tdddel dmdel</Names>
<Location>IND AUS ENG CAL JAP</Location>
</Employees>
</Employer>
...the desired (?) result is produced: ...产生所需的(?)结果:
<?xml version="1.0" encoding="UTF-8"?>
<Employer>
<Employees>
<Names>vel</Names>
<Location>ind</Location>
<Weather>26%</Weather>
</Employees>
<Employees>
<Names>bel</Names>
<Location>aus</Location>
<Weather>26%</Weather>
</Employees>
<Employees>
<Names>sel</Names>
<Location>eng</Location>
<Weather>26%</Weather>
</Employees>
<Employees>
<Names>tel</Names>
<Location>cal</Location>
<Weather>26%</Weather>
</Employees>
<Employees>
<Names>mel</Names>
<Location>jap</Location>
<Weather>26%</Weather>
</Employees>
<Employees>
<Names>asd</Names>
<Location>ind</Location>
<Weather>100%</Weather>
</Employees>
<Employees>
<Names>sadl</Names>
<Location>aus</Location>
<Weather>100%</Weather>
</Employees>
<Employees>
<Names>asdsel</Names>
<Location>eng</Location>
<Weather>100%</Weather>
</Employees>
<Employees>
<Names>tdddel</Names>
<Location>cal</Location>
<Weather>100%</Weather>
</Employees>
<Employees>
<Names>dmdel</Names>
<Location>jap</Location>
<Weather>100%</Weather>
</Employees>
</Employer>
Explanation: 说明:
<Employee>
elements, runs a special tokenize
template whose job it is to split your space-separate strings into result tree fragments. <Employee>
元素匹配的第二个模板运行一个特殊的tokenize
模板,该模板的工作是将以空格分隔的字符串拆分为结果树片段。 These fragments are saved into variables for convenience. token
. token
元素。 These are produced by EXSLT, which converts result tree fragments into node-sets comprised of <token>
elements. <token>
元素组成的节点集。 For each one of these, we pull the necessary element values to create <Names>
and <Location>
. <Names>
和<Location>
。 This template also contains the logic necessary to determine which value is required for the <weather>
element. <weather>
元素所需值的逻辑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.