1

我在 C++ 和 C# 应用程序中做了一些 XPath,但这是我第一次真正在 XSLT 中直接使用它。我有一个格式如下的 XML 文件:

<topLevel>
  <foo>
    <bar>prefix1_Taxi</bar>
    ...
  </foo>
  <foo>
    <bar>prefix1_SchoolBus</bar>
    ...
  </foo>
  ...
  <foo>
    <bar>prefix2_Taxi</bar>
    ...
  </foo>
  <foo>
    <bar>prefix2_SchoolBus</bar>
    ...
  </foo>
</topLevel>

首先,我只想选择<foo>元素<bar>以“prefix1_”开头的元素。这似乎有效:

<xsl:for-each select="foo[bar[starts-with(., 'prefix1_')]]">

   <!-- Style and format the values from child elements of the "prefix1_" <foo> -->

</xsl:for-each>

for-each然后,我想从块内部选择<foo>包含相应“prefix2_”元素的元素。然后,我想从每个我认为合适的地方提取数据。

For example, when the for-eachhas selected "prefix1_Taxi", I want to then select the fooelement that contains the "prefix2_Taxi" barelement.

<xsl:for-each select="foo[bar[starts-with(., 'prefix1_')]]">

   <!-- Retrieve the corresponding "prefix2_" foo -->
   <!-- Style and format the values from child elements of the "prefix1_" <foo> -->
   <!-- Style and format the values from child elements of the "prefix2_" <foo> -->

</xsl:for-each>

不幸的是,我不知道该怎么做。在传统程序中,我会执行以下伪代码:

String buf = barElement.Name.Replace("prefix1_", String.Empty);
XmlNode otherFoo = document.SelectSingleNode("foo[bar[" + buf + "]]");

然而,XSLT 显然使用不同的范例来检索值和操作数据,所以我试图打破我的旧思维模式。

使用我从 XSLT 上的一些谷歌搜索中收集到的内容,我想出了一些非常难看的东西:

  1. 选择包含以某些文本开头的条的 foo 元素:

    foo[bar[starts-with(., ...)

  2. 替换我们当前<bar>元素中的“prefix1_”:

    replace(<xsl:value-of select='bar'/>, 'prefix1_', '')

这会产生一个非常丑陋的混乱:

<xsl:value-of select="foo[bar[starts-with(., replace(<xsl:value-of select='bar'/>, 'prefix1_', ''))]]" />

我也很确定该<xsl:value-of>元素不正确。

我该怎么做?我怀疑我遗漏了一些关于如何在 XSLT 中表达这个概念的核心概念。我正在浏览 XSLT 上的w3.org 页面,但我仍然需要更多的学习和实践。

4

2 回答 2

2

这个 XSL 样式表应该为您提供一些关于如何处理foo包含“prefix2”的元素的灵活性。

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

  <!-- Matches the top level element and selects the children with prefix1 text. -->
  <xsl:template match="topLevel">
    <xsl:copy>
      <xsl:apply-templates select="foo[bar[starts-with(., 'prefix1_')]]"/>
    </xsl:copy>
  </xsl:template>

  <!-- We're at a foo element with prefix1 text. Select the siblings of the 
       same vehicle type, with prefix2 text. -->
  <xsl:template match="foo[bar[starts-with(., 'prefix1_')]]">
    <xsl:variable name="vehicle" select="substring-after(bar, 'prefix1_')"/>
    <xsl:apply-templates select="../foo[bar = concat('prefix2_', $vehicle)]"/>
  </xsl:template>

  <!-- In this template, you can do whatever you want with the foo element containing
       the prefix2 vehicles. This example just copies the element and its children. -->
  <xsl:template match="foo[bar[starts-with(., 'prefix2_')]]">
    <xsl:copy-of select="."/>
  </xsl:template>
</xsl:stylesheet>
于 2013-08-09T22:12:46.533 回答
1
<xsl:for-each select="foo[bar[starts-with(., 'prefix1_')]]">
    <xsl:variable name="new-text" as=xs:string" select="replace(bar/text(), '1', '2')" />
    <xsl:value-of select="concat(../foo/bar[$new-text]/text(), ' OR DO SOMETHING MORE USEFUL THAN APPENDING TEXT')" />  
</xsl:for-each>

您在foo循环中包含“prefix1”文本的元素上,然后更改为另一个 bar 元素的文本并对其进行操作,无论您想做什么。

备注:您可能需要添加xmlns:xs="http://www.w3.org/2001/XMLSchema"到您的 XSLT 根元素才能使xs:string我的示例中的 起作用。并且可能它在没有中间变量的情况下也可以工作,但我认为它使代码更具可读性。

于 2013-08-09T21:57:47.023 回答