我正在实现一个系统,用户可以在Items集合上生成文档。一个项目包含一个Name和一个ItemTypeId。用户可以选择要应用于特定类型的项目的模板。这存储在一个组合对象中,该对象包含itemTypeId到TemplateId的映射。
因此,用于生成文档的XML数据如下所示:
XML:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<composition>
<ItemType>
<ItemTypeId>IT1</ItemTypeId>
<TemplateId>T1</TemplateId>
</ItemType>
<ItemType>
<ItemTypeId>IT2</ItemTypeId>
<TemplateId>T3</TemplateId>
</ItemType>
<ItemType>
<ItemTypeId>IT3</ItemTypeId>
<TemplateId>T2</TemplateId>
</ItemType>
<ItemType>
<ItemTypeId>IT4</ItemTypeId>
<TemplateId>T1</TemplateId>
</ItemType>
</composition>
<items>
<item>
<ItemTypeId>IT1</ItemTypeId>
<Name>A</Name>
</item>
<item>
<ItemTypeId>IT2</ItemTypeId>
<Name>B</Name>
</item>
<item>
<ItemTypeId>IT3</ItemTypeId>
<Name>C</Name>
</item>
<item>
<ItemTypeId>IT2</ItemTypeId>
<Name>D</Name>
</item>
</items>
</data>
要生成文档,我想使用包含4个模板的XSLT。
XSLT:
<xsl:template match="/">
<html>
<body>
<h2>Document</h2>
<xsl:for-each select="/data/items/item">
<xsl:variable name="itemTypeId" select="current()/ItemTypeId" />
<xsl:apply-templates select="current()"/>
</xsl:for-each>
</body>
</html>
</xsl:template>
<xsl:template match="item[/data/composition/ItemType[ItemTypeId = current()/ItemTypeId]/TemplateId='T1']">
<h1>T1</h1>
Item <xsl:value-of select="current()/Name"/>
with type <xsl:value-of select="current()/ItemTypeId"/><br/>
</xsl:template>
<xsl:template match="item[/data/composition/ItemType[ItemTypeId = current()/ItemTypeId]/TemplateId='T2']">
<h1>T2</h1>
Item <xsl:value-of select="current()/Name"/>
with type <xsl:value-of select="current()/ItemTypeId"/><br/>
</xsl:template>
<xsl:template match="item[/data/composition/ItemType[ItemTypeId = current()/ItemTypeId]/TemplateId='T3']">
<h1>T3</h1>
Item <xsl:value-of select="current()/Name"/>
with type <xsl:value-of select="current()/ItemTypeId"/><br/>
</xsl:template>
<xsl:template match="item[/data/composition/ItemType[ItemTypeId = current()/ItemTypeId]/TemplateId='T4']">
<h1>T4</h1>
Item <xsl:value-of select="current()/Name"/>
with type <xsl:value-of select="current()/ItemTypeId"/><br/>
</xsl:template>
<xsl:template match="item">
</xsl:template>
我在匹配模式中使用current()函数查看合成,并查看是否需要应用模板。这可以在W3Schools的在线XSLT编辑器中完美运行,并生成以下文档:
输出(在W3Schools xslt编辑器上):
文档
T1
项目A,类型为IT1T3
项目B,类型为IT2T2
项目C,类型为IT3T3
项目D,类型为IT2
但是,当我尝试在.Net应用程序中实现此功能时,出现以下错误:
'current()'函数不能在模式中使用。
在我看来,.NET不允许在匹配模式中使用current()。有人知道解决这个问题的方法吗?还是有人可以指出我的逻辑缺陷?
编辑我使用System.Xml.Xsl中的标准.NET方法应用xslt,如下所示:
XElement data = XElement.Parse("xml is entered here");
XElement stylesheet = XElement.Parse("xslt is entered here");
XslCompiledTransform compiledTransform = new XslCompiledTransform();
compiledTransform.Load(stylesheet.CreateReader());
// Create an xml writer to write to the result stream.
using (XmlWriter writer = XmlWriter.Create(result, compiledTransform.OutputSettings))
{
// Apply the transformation.
compiledTransform.Transform(data.CreateReader(), null, writer);
}
// Return the result.
return result;
您可以使用一个键:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:key name="ref" match="data/composition/ItemType" use="ItemTypeId"/>
<xsl:template match="/">
<html>
<body>
<h2>Document</h2>
<xsl:apply-templates select="/data/items/item"/>
</body>
</html>
</xsl:template>
<xsl:template match="item[key('ref', ItemTypeId)/TemplateId='T1']">
<h1>T1</h1>
Item <xsl:value-of select="current()/Name"/>
with type <xsl:value-of select="current()/ItemTypeId"/><br/>
</xsl:template>
<xsl:template match="item[key('ref', ItemTypeId)/TemplateId='T2']">
<h1>T2</h1>
Item <xsl:value-of select="current()/Name"/>
with type <xsl:value-of select="current()/ItemTypeId"/><br/>
</xsl:template>
<xsl:template match="item[key('ref', ItemTypeId)/TemplateId='T3']">
<h1>T3</h1>
Item <xsl:value-of select="current()/Name"/>
with type <xsl:value-of select="current()/ItemTypeId"/><br/>
</xsl:template>
<xsl:template match="item[key('ref', ItemTypeId)/TemplateId='T4']">
<h1>T4</h1>
Item <xsl:value-of select="current()/Name"/>
with type <xsl:value-of select="current()/ItemTypeId"/><br/>
</xsl:template>
<xsl:template match="item">
</xsl:template>
</xsl:stylesheet>
看起来好像这四个模板可以更好地简化为单个模板
<xsl:template match="item[key('ref', ItemTypeId)]">
<h1><xsl:value-of select="key('ref', ItemTypeId)/TemplateId"/></h1>
Item <xsl:value-of select="Name"/>
with type <xsl:value-of select="ItemTypeId"/><br/>
</xsl:template>
或者,您需要切换到XSLT 2.0处理器,例如Saxon 9或XmlPrime,其中current()
支持在模式中使用XSLT 2.0处理器。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句