我在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
块内部,我想要选择包含相应“prefix2_”元素的<foo>
元素。然后,我想在我认为合适的情况下从每个数据中提取数据。
例如,当for-each
选择了“prefix1_Taxi”时,我想选择包含“prefix2_Taxi”foo
元素的bar
元素。
<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显然可以使用不同的范例来检索值和操作数据,因此我试图摆脱旧的思维模式。
使用我在谷歌搜索中搜索的一些搜索,我想出了一些非常难看的东西:
选择包含以某些文本开头的小节的foo元素:
foo[bar[starts-with(., ...)
替换当前<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 page,但我还需要多进行更多的学习和练习。
答案 0 :(得分:2)
此XSL样式表应该为您对包含“prefix2”的foo
元素所做的操作提供一些灵活性。
<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>
答案 1 :(得分: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>
你在循环中包含“prefix1”文本的foo
元素,然后更改为其他bar元素的文本并对其进行操作,无论你想做什么。
备注:您可能需要将xmlns:xs="http://www.w3.org/2001/XMLSchema"
添加到XSLT根元素中,以使我的示例中的xs:string
生效。并且可能它也可以在没有中间变量的情况下工作,但我认为它使代码更具可读性。