Ошибка с XSLT XPATH (выражение должно оцениваться как набор узлов) - PullRequest
0 голосов
/ 01 апреля 2020

У меня есть 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();
}

Я получил это исключение, как прокомментировано в коде (// выражение должно вычисляться для набора узлов). Однако, когда я использую «(// Employee) [1]» или «// Employee» непосредственно в файле XSLT вместо использования параметра (SLCT), я получаю нужный результат. Итак, в чем здесь проблема?

Ответы [ 2 ]

0 голосов
/ 01 апреля 2020

Выражение XPath, используемое в атрибуте select инструкции xsl:for-each, не может быть вычислено динамически во время выполнения.

Поскольку ваш XML использует другое имя элемента для каждой записи сотрудника (Employee, Employee0, Employee1 и т. Д. c.), Вы можете передать имя нужного элемента в качестве параметра и затем выберите правильный элемент, используя предикат.

Например, следующая таблица стилей:

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>

при вызове с помощью значение "Employee0" для параметра SLCT вернет:

Результат

<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>
0 голосов
/ 01 апреля 2020

Ваш XML нуждается в некотором улучшении. Для каждого сотрудника не нужно иметь разные имена элементов XML. И вы можете получить конкретного сотрудника на основе уникального значения элемента ID: 100, 101 и т. Д. c. Я настроил 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...