我正在编写一个XSL转换,在该转换中,我无法移动到根节点并访问每个节点内部的其他节点。
假设我在一个上下文中。我有一种情况,我必须去到外部节点,从那里获得一个值,然后返回到相同的上下文。
这是我的XML文件。
<xml version=1.0>
<abc>
<parts>
<part pno="10506">
<pname>Land Before Time I</pname>
<qoh>200</qoh>
<price>19.99</price>
<level>20</level>
</part>
…
</parts>
<orders>
<order ono="1022" takenBy="1001" customer="2222">
<receivedDate>1995-02-13</receivedDate>
<shippedDate>1995-02-20</shippedDate>
<items>
<item>
<partNumber>10601</partNumber>
<quantity>1</quantity>
</item>
<item>
<partNumber>10701</partNumber>
<quantity>1</quantity>
</item>
</items>
</order>
.....
</orders>
</abc>
我在xsl:for-each中的"item"标记内迭代,但我想进入"part"标记并获取一个值,然后返回到相同的上下文。
更详细地说:我正在填满一张桌子。我的表有4列:
- partname:我必须去
<part>
才能得到这个名字。(这就是我被卡住的地方( - quantity:这对我来说不是问题,因为它是
<item>
的子元素 - 普莱斯:我也面临同样的问题
- total:很容易
请帮我从零件标签中获取零件名称和价格的值。
以下代码对我不起作用。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet>
<table>
<xsl:param name="param1" />
<xsl:variable name="temp" select ="name(/*)"/>
<xsl:for-each select=".//order[@ono=$param1]/items/item">
<tr>
<td> <xsl:value-of select="$temp//part[@pno=partNumber]/pname"/> </td>
<td> <xsl:value-of select="quantity"/> </td>
<td> <xsl:value-of select="$temp//part[@pno=partNumber]/price"/> </td>
<td> <xsl:value-of select="quantity*$temp//part[@pno=partNumber]/price"/> </td>
</tr>
</xsl:for-each>
</table>
<xsl:stylesheet>
我试着在谷歌上搜索,但找不到问题的确切答案。我写的代码出现了一些错误。我尝试将"temp"的选择值更改为root(.(,但它不起作用。
我只需要一个提示。我不需要答案。只要一个提示对我来说就足够了。
在过去的5个小时里,我一直在纠结这个问题。请回复并帮助我。
当您想从谓词内部引用与当前上下文相关的内容时,可以使用current()
:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="param1" select="1022" />
<xsl:template match="/">
<table>
<xsl:for-each select="//order[@ono=$param1]/items/item">
<tr>
<td>
<xsl:value-of select="//part[@pno=current()/partNumber]/pname"/>
</td>
<td>
<xsl:value-of select="quantity"/>
</td>
<td>
<xsl:value-of select="//part[@pno=current()/partNumber]/price"/>
</td>
<td>
<xsl:value-of select="quantity * //part[@pno=current()/partNumber]/price"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
然而,这里更有效的方法是使用密钥。我还对XSLT进行了一些清理,以更好地利用模板并避免路径中的重复:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="kPart" match="part" use="@pno" />
<xsl:param name="param1" select="1022" />
<xsl:template match="/">
<table>
<xsl:apply-templates select="//order[@ono=$param1]/items/item" />
</table>
</xsl:template>
<xsl:template match="item">
<xsl:variable name="part" select="key('kPart', partNumber)" />
<tr>
<td>
<xsl:value-of select="$part/pname"/>
</td>
<td>
<xsl:value-of select="quantity"/>
</td>
<td>
<xsl:value-of select="$part/price"/>
</td>
<td>
<xsl:value-of select="quantity * $part/price"/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
根不是.
。根为/
。如果您想要元素名称为"part"的根的任何后代,则使用//part
。
如果在<table>
之前放<xsl:template match="/">
,在</table>
之后放</xsl:template>
,那么当XML解析器解析文档根时,XSL处理器将生成您的表元素。
您的xsl:stylesheet
打开标记需要几个属性。对于XSLT1.0,它应该是<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
。
我认为这一点点信息可能足以让它发挥作用。
如果你需要提高效率,你应该避免使用//
,而使用xsl:key
。您可以在XSL转换规范中找到xsl:key
的定义、基本原理和简单示例。