pen*_*tur 13 xslt xpath nested predicate
似乎这个问题之前没有在stackoverflow上讨论过,除了使用嵌套的XPath Predicates ...精炼在哪里提供了不涉及嵌套谓词的解决方案.
所以我试着写出我想要得到的过度简化的样本:
输入:
<root>
<shortOfSupply>
<food animal="doggie"/>
<food animal="horse"/>
</shortOfSupply>
<animalsDictionary>
<cage name="A" animal="kittie"/>
<cage name="B" animal="dog"/>
<cage name="C" animal="cow"/>
<cage name="D" animal="zebra"/>
</animals>
</root>
Run Code Online (Sandbox Code Playgroud)
输出:
<root>
<hungryAnimals>
<cage name="B"/>
<cage name="D"/>
</hungryAnimals>
</root>
Run Code Online (Sandbox Code Playgroud)
或者,如果没有交叉点,
<root>
<everythingIsFine/>
</root>
Run Code Online (Sandbox Code Playgroud)
我想使用嵌套谓词来获取它:
<xsl:template match="cage">
<cage>
<xsl:attribute name="name">
<xsl:value-of select="@name"/>
</xsl:attribute>
</cage>
</xsl:template>
<xsl:template match="/root/animalsDictionary">
<xsl:choose>
<!-- in <food> in <cage> -->
<xsl:when test="cage[/root/shortOfSupply/food[ext:isEqualAnimals(./@animal, ?????/@animal)]]">
<hungryAnimals>
<xsl:apply-templates select="cage[/root/shortOfSupply/food[ext:isEqualAnimals(@animal, ?????/@animal)]]"/>
</hungryAnimals>
</xsl:when>
<xsl:otherwise>
<everythingIsFine/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)
那么我该?????怎么写呢呢?
我知道我可以使用一个更多的模板和变量/参数的广泛使用来重写整个样式表,但它甚至使这个样式表变得更加复杂,更不用说真实问题的真实样式表了.
它在XPath引用中写入,点.符号表示当前上下文节点,但它没有告诉在此之前是否有可能获取上下文节点; 我无法相信XPath缺少这个明显的功能.
Dim*_*hev 10
XPath 2.0单线程:
for $a in /*/animalsDictionary/cage
return
if(/*/shortOfSupply/*[my:isA($a/@animal, @animal)])
then $a
else ()
Run Code Online (Sandbox Code Playgroud)
当应用于提供的XML文档时,选择:
<cage name="B"/>
<cage name="D"/>
Run Code Online (Sandbox Code Playgroud)
不能使用单个XPath 1.0表达式来发现给定的笼子包含饥饿的动物.
这是一个XSLT解决方案(XSLT 2.0仅用于避免使用扩展函数进行比较 - 在XSLT 1.0解决方案中,将使用扩展函数进行比较,并使用xxx:node-set()扩展来测试是否通过在模板中应用模板生成的RTF变量的主体包含任何子元素):
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="my:my" exclude-result-prefixes="xs my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<my:Dict>
<a genName="doggie">
<name>dog</name>
<name>bulldog</name>
<name>puppy</name>
</a>
<a genName="horse">
<name>horse</name>
<name>zebra</name>
<name>pony</name>
</a>
<a genName="cat">
<name>kittie</name>
<name>kitten</name>
</a>
</my:Dict>
<xsl:variable name="vDict" select=
"document('')/*/my:Dict/a"/>
<xsl:template match="/">
<root>
<xsl:variable name="vhungryCages">
<xsl:apply-templates select=
"/*/animalsDictionary/cage"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="$vhungryCages/*">
<hungryAnimals>
<xsl:copy-of select="$vhungryCages"/>
</hungryAnimals>
</xsl:when>
<xsl:otherwise>
<everythingIsFine/>
</xsl:otherwise>
</xsl:choose>
</root>
</xsl:template>
<xsl:template match="cage">
<xsl:if test="
/*/shortOfSupply/*[my:isA(current()/@animal,@animal)]">
<cage name="{@name}"/>
</xsl:if>
</xsl:template>
<xsl:function name="my:isA" as="xs:boolean">
<xsl:param name="pSpecName" as="xs:string"/>
<xsl:param name="pGenName" as="xs:string"/>
<xsl:sequence select=
"$pSpecName = $vDict[@genName = $pGenName]/name"/>
</xsl:function>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
当对提供的XML文档应用此转换时(已更正为格式正确):
<root>
<shortOfSupply>
<food animal="doggie"/>
<food animal="horse"/>
</shortOfSupply>
<animalsDictionary>
<cage name="A" animal="kittie"/>
<cage name="B" animal="dogs"/>
<cage name="C" animal="cow"/>
<cage name="D" animal="zebras"/>
</animalsDictionary>
</root>
Run Code Online (Sandbox Code Playgroud)
产生了想要的正确结果:
<root>
<hungryAnimals>
<cage name="B"/>
<cage name="D"/>
</hungryAnimals>
</root>
Run Code Online (Sandbox Code Playgroud)
说明:请注意使用XSLT current()函数.
| 归档时间: |
|
| 查看次数: |
7451 次 |
| 最近记录: |