如何获取外部谓词的上下文

如何获取外部谓词的上下文

本文介绍了XPath/XSLT嵌套谓词:如何获取外部谓词的上下文?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

似乎以前没有在stackoverflow上讨论过这个问题,除了使用嵌套XPath谓词...已精炼,其中提供了不涉及嵌套谓词的解决方案.

It seems that this question was not discussed on stackoverflow before, save for Working With Nested XPath Predicates ... Refined where the solution not involving nested predicates was offered.

所以我试图写出我想要得到的东西的过度简化的例子:

So I tried to write the oversimplified sample of what I'd like to get:

输入:

<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>

输出:

<root>
    <hungryAnimals>
        <cage name="B"/>
        <cage name="D"/>
    </hungryAnimals>
</root>

或者,如果没有交叉路口,

or, alternatively, if there is no intersections,

<root>
    <everythingIsFine/>
</root>

我想使用嵌套谓词来获取它:

And i want to get it using a nested predicates:

<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>

那么我应该写些什么代替那个??????

So what should i write in place of that ??????

我知道我可以使用另一个模板并广泛使用变量/参数来重写整个样式表,但这甚至使该样式表变得更加复杂,更不用说真正的样式表了.

I know i could rewrite the entire stylesheet using one more template and extensive usage of variables/params, but it makes even this stylesheet significantly more complex, let alone the real stylesheet i have for real problem.

在XPath参考文献中,点.符号表示当前上下文节点,但是它并没有告诉我们是否有可能在此之前获取上下文节点;而且我简直不敢相信XPath缺少这个明显的功能.

It is written in XPath reference that the dot . sign means the current context node, but it doesn't tell whether there is any possibility to get the node of context before that; and i just can't believe XPath is missing this obvious feature.

推荐答案

XPath 2.0单线版:

for $a in /*/animalsDictionary/cage
      return
        if(/*/shortOfSupply/*[my:isA($a/@animal, @animal)])
          then $a
          else ()

应用于提供的XML文档时,选择:

   <cage name="B"/>
   <cage name="D"/>

一个人不能使用单个XPath 1.0表达式来查找给定的笼子里有饥饿的动物.

这里是XSLT解决方案(XSLT 2.0仅用于避免使用扩展功能进行比较-在XSLT 1.0解决方案中,将使用扩展功能进行比较,而扩展,以测试通过在变量的主体中应用模板而产生的RTF是否包含任何子元素:

Here is an XSLT solution (XSLT 2.0 is used only to avoid using an extension function for the comparison -- in an XSLT 1.0 solution one will use an extension function for the comparison and the xxx:node-set() extension to test if the RTF produced by applying templates in the body of the variable contains any child element):

<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>

将此转换应用于提供的XML文档(已更正,格式正确):

When this transformation is applied on the provided XML document (corrected to be well-formed):

<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>

产生了所需的正确结果:

<root>
   <hungryAnimals>
      <cage name="B"/>
      <cage name="D"/>
   </hungryAnimals>
</root>

说明:请注意XSLT current()函数的使用.

Explanation: Do note the use of the XSLT current() function.

这篇关于XPath/XSLT嵌套谓词:如何获取外部谓词的上下文?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-29 13:51