XSLT XPATH错误(表达式的计算结果必须为节点集)



我有如下的XML

<Employees>
<Employee>
<ID>100</ID>
<FirstName>Bala</FirstName>
<LastName>Murugan</LastName>
<Dept>Production Support</Dept>
</Employee>
<Employee0>
<ID>101</ID>
<FirstName>Peter</FirstName>
<LastName>Laurence</LastName>
<Dept>Development</Dept>
</Employee0>
<Employee1>
<ID>102</ID>
<FirstName>Rick</FirstName>
<LastName>Anderson</LastName>
<Dept>Sales</Dept>
</Employee1>
</Employees>

我想展示其中一名员工使用以下XSLT

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="SLCT"/>
<xsl:template match="/">
<xsl:for-each select="$SLCT">
<div style="border:1px black solid;width:300px;margin:1px">
<div>
<b>Employee ID:</b>
<xsl:value-of select="ID"/>
</div>
<div>
<b>Name:</b>
<xsl:value-of select="FirstName"/>
<xsl:text> </xsl:text>
<xsl:value-of select="LastName"/>
</div>
<div>
<b>Department:</b>
<xsl:value-of select="Dept"/>
</div>
</div>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

(对于每个select="$SLCT"(的问题,它不接受C#中的参数。

我的C#代码

protected void Page_Load(object sender, EventArgs e)
{
string strXSLTFile = Server.MapPath("EmployeeXSLT.xslt");
string strXMLFile = Server.MapPath("Employess.xml");
XmlReader reader = XmlReader.Create(strXMLFile);
XslCompiledTransform objXSLTransform = new XslCompiledTransform();
objXSLTransform.Load(strXSLTFile);
// Create the XsltArgumentList.
XsltArgumentList argList = new XsltArgumentList();
// Set new value to the parameter
argList.AddParam("SLCT", "", "(//Employee)[1]");
XmlWriter writer = XmlWriter.Create(Server.MapPath("OutPut.xml"));
objXSLTransform.Transform(new XPathDocument(strXMLFile), argList, writer); 
//Expression must evaluate to a node-set
writer.Close(); 
reader.Close();
Xml2.DocumentSource = Server.MapPath("~/test/Employess.xml");
Xml2.TransformSource = Server.MapPath("~/test/OutPut.xml");
Xml2.DataBind();
}

我得到了代码中注释的这个异常(//表达式必须计算为节点集(。但是,当我在XSLT文件中直接使用"(//Employee([1]"或"//Employer"而不是使用参数(SLCT(时,我会得到所需的结果。那么,问题出在哪里呢?

xsl:for-each指令的select属性中使用的XPath表达式在运行时无法动态计算。

由于XML为每个员工记录使用不同的元素名称(EmployeeEmployee0Employee1等(,因此可以传递所需元素的名称作为参数,然后使用谓词选择正确的元素。

例如,以下样式表:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:param name="SLCT"/>
<xsl:template match="/Employees">
<xsl:variable name="emp" select="*[name()=$SLCT]" />
<div>
<b>Employee ID:</b>
<xsl:value-of select="$emp/ID"/>
</div>
</xsl:template>
</xsl:stylesheet>

当使用SLCT参数的"Employee0"值调用时,将返回:

结果

<div><b>Employee ID:</b>101</div>

注意
由于只有一个元素满足谓词,所以我使用了一个变量而不是xsl:for-each。但使用也同样有效

<xsl:template match="/Employees">
<xsl:for-each select="*[name()=$SLCT]">
<div>
<b>Employee ID:</b>
<xsl:value-of select="ID"/>
</div>
</xsl:for-each>
</xsl:template>

您的XML需要一些改进。不需要为每个员工提供不同的XML元素名称。您可以根据唯一的ID元素值检索特定的员工:100、101等。我调整了XSLT以接受该类型的参数。请在下面查看。

XML

<?xml version="1.0"?>
<Employees>
<Employee>
<ID>100</ID>
<FirstName>Bala</FirstName>
<LastName>Murugan</LastName>
<Dept>Production Support</Dept>
</Employee>
<Employee>
<ID>101</ID>
<FirstName>Peter</FirstName>
<LastName>Laurence</LastName>
<Dept>Development</Dept>
</Employee>
<Employee>
<ID>102</ID>
<FirstName>Rick</FirstName>
<LastName>Anderson</LastName>
<Dept>Sales</Dept>
</Employee>
</Employees>

XSLT

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" omit-xml-declaration="yes"/>
<xsl:param name="SLCT">100</xsl:param>
<xsl:template match="/">
<xsl:apply-templates select="Employees/Employee[ID=$SLCT]"/>
</xsl:template>
<xsl:template match="Employee">
<div style="border:1px black solid;width:300px;margin:1px">
<div>
<b>Employee ID:</b>
<xsl:value-of select="ID"/>
</div>
<div>
<b>Name:</b>
<xsl:value-of select="concat(FirstName,' ',LastName)"/>
</div>
<div>
<b>Department:</b>
<xsl:value-of select="Dept"/>
</div>
</div>
</xsl:template>
</xsl:stylesheet>

c#

// Set new value to the parameter
argList.AddParam("SLCT", "", "101");

输出

<div style="border:1px black solid;width:300px;margin:1px">
<div>
<b>Employee ID:</b>101
</div>
<div>
<b>Name:</b>Peter Laurence
</div>
<div>
<b>Department:</b>Development
</div>
</div>

最新更新