无法使用XPath获取节点,该节点从输入中读取所需的ID



我试图通过动态创建xpath来获取XML节点的属性值。但是它一直在返回空值。如果我对XPath进行硬编码,则可以正常工作。以下是示例XML文件:

<root>  
<PR id="id6016" name="OUTER WORLD">
    <ADS id="id6017" dsRef="#id15" role="form1">
    </ADS>
    <ADS id="id6018" dsRef="#id9" role="form1">
    </ADS>
</PR>
<PR id="id1000" name="OUTER WORLD">
    <ADS id="id1001" dsRef="#id16" role="form1">
    </ADS>
    <ADS id="id1002" dsRef="#id10" role="form1">
    </ADS>
</PR>
<DS id="id9" name="form1" version="7" type="CAD">
</DS>
<DS id="id15" name="form1" version="1" type="MSWord">
</DS>
<DS id="id10" name="form1" version="1" type="CAD">
</DS>
<DS id="id16" name="form1" version="1" type="MSWord">
</DS>
</root>

我的样本XSL是:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" omit-xml-declaration="no" indent="no" encoding="utf-8"/>
  <xsl:template match="/root">
    <result>
      <xsl:apply-templates select="PR" mode="PR" />
    </result>
  </xsl:template>
  <xsl:template match="PR" mode="PR">
    <PR>
      <xsl:attribute name="id">
        <xsl:value-of select="@id" />
      </xsl:attribute>
      <xsl:attribute name="name">
        <xsl:value-of select="@name" />
      </xsl:attribute>
      <xsl:for-each select="ADS[@role='form1']">
        <DS>
          <xsl:attribute name="id">
            <xsl:value-of select="string(substring-after(@dsRef, '#'))" />
          </xsl:attribute>
          <xsl:value-of select="../DS[@id=string(substring-after(@dsRef, '#'))]/@type" />
        </DS>           
      </xsl:for-each>
      <DS2>
        <xsl:value-of select="../DS[@id='id9']/@type" />
      </DS2>      
      <DS3>
        <xsl:value-of select="../DS[@id=string(substring-after(@dsRef, '#'))]/@type" />
      </DS3>
    </PR>
  </xsl:template>
</xsl:stylesheet>

您可以看到,我对DS2标签有任何Innertext,但对于DS或DS3而言。我还将ID属性添加到DS标签中,以表明我获得的ID很好。

最终我想过滤具有type =" cad"并将其ID存储在变量中的DS标签,但是现在我无法使用XPath获取XML节点,因此我被卡住了。

如果我正确理解了您对问题的描述,则指令

<xsl:value-of select="../DS[@id='id9']/@type" />

在DS2元素中正在产生预期和所需的值,但是指令

<xsl:value-of select="../DS[@id=string(substring-after(@dsRef, '#'))]/@type" />

在DS3元素中不是。同样,在XSL中生成的DS元素上的@ID属性:for-eht具有期望值,但是元素内容不如预期。(专家提示:如果不是很琐事,您将有更好的运气引起堆栈溢出问题的答案

您在这里有两个问题。

首先,对@dsRef的引用在第一个XSL:XSL:for-EAST的XSL:foration中成功,因为该属性引用的上下文元素是带有dsRef元素的ADS元素。第二个XSL中对@dsRef的引用:XSL的值:for-east失败,因为它在谓词内部,并且上下文元素是对谓词进行测试的DS元素。DS3调试元素中对@dsRef的引用同样是对DS元素上不存在的" DSREF"属性的引用。

有两种解决此问题的方法。您可以在current()上阅读,其中包括从谓词内部指向整个XPATH表达式的上下文元素的一种方式,并将属性引用重写为类似于current()/@dsRef的内容。许多人会推荐这条道路。

或者您可以避免了解current(),以及在任何给定点上爬上的上下文节点的堆栈,并将您想要的值绑定到可以在表达式中引用的变量。(我从经验中知道,可以花费数年的时间编写XSLT程序,而不需要理解current()的所有细节。)在这种情况下,您的for-EATH会看起来像这样:

<xsl:for-each select="ADS[@role='form1']">
  <xsl:variable name="targetDS" select="substring-after(@dsRef,'#')"/>
  <DS>
    <xsl:attribute name="id">
      <xsl:value-of select="$targetDS" />
    </xsl:attribute>
    <xsl:value-of select="../DS[@id=$targetDS]/@type" />
  </DS>           
</xsl:for-each>

您可能会发现(就像我一样),在指定变量中具有目标ID使得更容易理解两个指令正在做什么。

此更改后,您的程序仍然不起作用。

您的第二个问题是您正在寻找当前广告元素的兄弟姐妹之间的DS元素,但是输入中的ADS元素实际上没有DS兄弟姐妹。他们都是PR的兄弟姐妹。如果您的元素上的" ID"属性以XML ID的形式行为,则该元素的层次位置是无关紧要的,并且更简单的表达式(例如

//DS[@id=$targetDS]

将更具弹性(更清晰)。如果您有DTD,并且" ID"属性被声明为具有类型ID,那么编写

甚至更简单
id($targetDS)

这意味着" ID为$ targets的元素"。如果由于某种原因您真的想将表达式限制为输入文档特定区域中的DS元素,则需要确保正确地参考该区域。我用../..替换..后,样式表产生了我认为的预期结果。

相关内容

  • 没有找到相关文章

最新更新