Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml XSLT——解释文本节点';s值作为XPath查询(并在转换中使用)_Xml_Xslt_Xpath - Fatal编程技术网

Xml XSLT——解释文本节点';s值作为XPath查询(并在转换中使用)

Xml XSLT——解释文本节点';s值作为XPath查询(并在转换中使用),xml,xslt,xpath,Xml,Xslt,Xpath,我一直在试图找到一个体面的解决办法,但我甚至找不到一个不体面的办法 我有一个XML文件,看起来有点像这样: <Root> <Something> <SomethingElse>Value of SomethingElse</SomethingElse> </Something> ... <Map> <Node> <Path&

我一直在试图找到一个体面的解决办法,但我甚至找不到一个不体面的办法

我有一个XML文件,看起来有点像这样:

<Root>
    <Something>
        <SomethingElse>Value of SomethingElse</SomethingElse>
    </Something>

...

    <Map>
        <Node>
            <Path>/Root/Something/SomethingElse</Path>
        </Node>
    <Map>

...

</Root>
我首先想到的是:

<xsl:template match="Path">
    <text><xsl:value-of select="{text()}"/></text>
</xsl:template>

但这当然不起作用,因为
select
不是值属性

我不知道该怎么办。谷歌搜索只返回关于如何使用XPath获取文本值的结果,而不是相反

我还想对返回的
元素应用进一步的转换,但一旦我弄明白如何做,这应该是小菜一碟

非常感谢您能走到这一步,

Slampisko

对于纯XSLT1.0甚至2.0,您需要使用两个样式表,第一个样式表接受输入并使用您想要使用的XPath表达式创建第二个样式表作为结果,然后针对原始输入运行第二个样式表


或者,您需要检查XSLT处理器是否支持扩展函数将字符串作为路径表达式进行求值,就像Saxon使用altova:evaluate函数或AltovaXML使用altova:evaluate函数一样。

而完整的动态XPath求值不是XSLT 1.0/XPath 1.0或XSLT 2.0/XPath 2.0的一部分,我们可以生成一个XSLT 1.0实现,它的工作方式相当有限

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="text()"/>

 <xsl:template match="Path" name="eval">
  <xsl:param name="pPath" select="."/>
  <xsl:param name="pContext" select="/"/>

  <xsl:choose>
   <!-- If there is something to evaluate -->
   <xsl:when test="string-length($pPath) >0">
      <xsl:variable name="vPath" select=
          "substring($pPath,2)"/>

      <xsl:variable name="vNameTest">
       <xsl:choose>
        <xsl:when test="not(contains($vPath, '/'))">
         <xsl:value-of select="$vPath"/>
        </xsl:when>
        <xsl:otherwise>
         <xsl:value-of select=
             "substring-before($vPath, '/')"/>
        </xsl:otherwise>
       </xsl:choose>
      </xsl:variable>

      <xsl:call-template name="eval">
       <xsl:with-param name="pPath" select=
         "substring-after($pPath, $vNameTest)"/>
       <xsl:with-param name="pContext" select=
        "$pContext/*[name()=$vNameTest]"/>
      </xsl:call-template>
  </xsl:when>
  <!-- Otherwise we have evaluated completely the path -->
  <xsl:otherwise>
   <xsl:copy-of select="$pContext"/>
  </xsl:otherwise>
  </xsl:choose>
 </xsl:template>
</xsl:stylesheet>
<Root>
    <Something>
        <SomethingElse>Value of SomethingElse</SomethingElse>
    </Something>

...

    <Map>
        <Node>
            <Path>/Root/Something/SomethingElse</Path>
        </Node>
    </Map>

...

</Root>
<SomethingElse>Value of SomethingElse</SomethingElse>

当此转换应用于提供的XML文档时

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="text()"/>

 <xsl:template match="Path" name="eval">
  <xsl:param name="pPath" select="."/>
  <xsl:param name="pContext" select="/"/>

  <xsl:choose>
   <!-- If there is something to evaluate -->
   <xsl:when test="string-length($pPath) >0">
      <xsl:variable name="vPath" select=
          "substring($pPath,2)"/>

      <xsl:variable name="vNameTest">
       <xsl:choose>
        <xsl:when test="not(contains($vPath, '/'))">
         <xsl:value-of select="$vPath"/>
        </xsl:when>
        <xsl:otherwise>
         <xsl:value-of select=
             "substring-before($vPath, '/')"/>
        </xsl:otherwise>
       </xsl:choose>
      </xsl:variable>

      <xsl:call-template name="eval">
       <xsl:with-param name="pPath" select=
         "substring-after($pPath, $vNameTest)"/>
       <xsl:with-param name="pContext" select=
        "$pContext/*[name()=$vNameTest]"/>
      </xsl:call-template>
  </xsl:when>
  <!-- Otherwise we have evaluated completely the path -->
  <xsl:otherwise>
   <xsl:copy-of select="$pContext"/>
  </xsl:otherwise>
  </xsl:choose>
 </xsl:template>
</xsl:stylesheet>
<Root>
    <Something>
        <SomethingElse>Value of SomethingElse</SomethingElse>
    </Something>

...

    <Map>
        <Node>
            <Path>/Root/Something/SomethingElse</Path>
        </Node>
    </Map>

...

</Root>
<SomethingElse>Value of SomethingElse</SomethingElse>

某物的价值
...
/根/某物/某物
...
生成所需的正确结果

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="text()"/>

 <xsl:template match="Path" name="eval">
  <xsl:param name="pPath" select="."/>
  <xsl:param name="pContext" select="/"/>

  <xsl:choose>
   <!-- If there is something to evaluate -->
   <xsl:when test="string-length($pPath) >0">
      <xsl:variable name="vPath" select=
          "substring($pPath,2)"/>

      <xsl:variable name="vNameTest">
       <xsl:choose>
        <xsl:when test="not(contains($vPath, '/'))">
         <xsl:value-of select="$vPath"/>
        </xsl:when>
        <xsl:otherwise>
         <xsl:value-of select=
             "substring-before($vPath, '/')"/>
        </xsl:otherwise>
       </xsl:choose>
      </xsl:variable>

      <xsl:call-template name="eval">
       <xsl:with-param name="pPath" select=
         "substring-after($pPath, $vNameTest)"/>
       <xsl:with-param name="pContext" select=
        "$pContext/*[name()=$vNameTest]"/>
      </xsl:call-template>
  </xsl:when>
  <!-- Otherwise we have evaluated completely the path -->
  <xsl:otherwise>
   <xsl:copy-of select="$pContext"/>
  </xsl:otherwise>
  </xsl:choose>
 </xsl:template>
</xsl:stylesheet>
<Root>
    <Something>
        <SomethingElse>Value of SomethingElse</SomethingElse>
    </Something>

...

    <Map>
        <Node>
            <Path>/Root/Something/SomethingElse</Path>
        </Node>
    </Map>

...

</Root>
<SomethingElse>Value of SomethingElse</SomethingElse>
SomethingElse的值
我们假设以下限制条件

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="text()"/>

 <xsl:template match="Path" name="eval">
  <xsl:param name="pPath" select="."/>
  <xsl:param name="pContext" select="/"/>

  <xsl:choose>
   <!-- If there is something to evaluate -->
   <xsl:when test="string-length($pPath) >0">
      <xsl:variable name="vPath" select=
          "substring($pPath,2)"/>

      <xsl:variable name="vNameTest">
       <xsl:choose>
        <xsl:when test="not(contains($vPath, '/'))">
         <xsl:value-of select="$vPath"/>
        </xsl:when>
        <xsl:otherwise>
         <xsl:value-of select=
             "substring-before($vPath, '/')"/>
        </xsl:otherwise>
       </xsl:choose>
      </xsl:variable>

      <xsl:call-template name="eval">
       <xsl:with-param name="pPath" select=
         "substring-after($pPath, $vNameTest)"/>
       <xsl:with-param name="pContext" select=
        "$pContext/*[name()=$vNameTest]"/>
      </xsl:call-template>
  </xsl:when>
  <!-- Otherwise we have evaluated completely the path -->
  <xsl:otherwise>
   <xsl:copy-of select="$pContext"/>
  </xsl:otherwise>
  </xsl:choose>
 </xsl:template>
</xsl:stylesheet>
<Root>
    <Something>
        <SomethingElse>Value of SomethingElse</SomethingElse>
    </Something>

...

    <Map>
        <Node>
            <Path>/Root/Something/SomethingElse</Path>
        </Node>
    </Map>

...

</Root>
<SomethingElse>Value of SomethingElse</SomethingElse>
  • 我们计算的每个XPath表达式必须由一系列名称测试组成,由XPath“/”运算符分隔——也就是说,每个位置步骤只指定一个元素名称

  • 任何位置步骤中都不能包含轴或谓词


  • 好问题,+1。请参阅我的答案,了解一个完整的XSLT1.0解决方案,如果接受了某些限制,该解决方案是可能的和有用的。这就是我所想的,但扩展到处理谓词是非常困难的,不是吗?@empo:是的,编写一个完整的XPath引擎即使在C#中也不容易。在XSLT1.0中,这将是非常困难的。我的XPath2.0解析器是用XSLT2.0编写的——很有可能做到,但仍然很有挑战性。投票支持这项努力。我可能会处理这种方法,但我的XPath(文本节点中的XPath)不是一系列名称测试,而是相当复杂的查询(嗯,不太复杂……不过我会测试属性值)。我举的这个简单的例子纯粹是为了让我的问题简单易懂。@Slampisko:属性测试可以很容易地添加到这个解决方案中。请更新您的问题,我很乐意回答。:)谢谢,这似乎是我一直在寻找的答案。