繁体   English   中英

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

[英]Error with XSLT XPATH (Expression must evaluate to a node-set)

我有如下的 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>

(for-each 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();
}

我得到了代码中注释的这个异常(//Expression must evaluate to a node-set)。 但是,当我直接在 XSLT 文件中使用“(//Employee)[1]”或“//Employee”而不是使用参数 (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>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM