XSLT Batch Processing

本文关键字:Processing Batch XSLT | 更新日期: 2023-09-27 18:27:25

我有以下XML结构:

<School>
  <SchoolInfo>
    <SchoolName>The Big School</SchoolName>
    <Opened>2008</Opened>
    <SchoolID>SCH1122</SchoolID>
    <Geograpics>
      <Location>London</Location>
      <PostCode>ZZ11 1ZZ</PostCode>
    </Geographics>
  </SchoolInfo>
  <Pupil>
    <Name>Tom</Name>
    <LastName>Jones</LastName>
    <Class>12B</Class>
    <Age>16</Age>
  </Pupil>
  <Pupil>
    <Name>Steve</Name>
    <LastName>Jobs</LastName>
    <Class>09A</Class>
    <Age>17</Age>
  </Pupil>
  <Pupil>
    <Name>Joe</Name>
    <LastName>Blogs</LastName>
    <Class>13A</Class>
    <Age>15</Age>
  </Pupil>
</School>

如果我的XML结构包含。。400名学生和我想以50名学生为一批进行处理,并为每50名学生写下PSV,所以前50名,然后50-100名,然后100-150名,以此类推,并将每一批写到一个新文件中。。这可以使用XSLT完成吗?还是必须是程序化的?

我现在有了要处理到PSV等的代码,我只是被如何批量处理所困扰,因为坦率地说,我一点都不知道!

--PSV:管道分离值

SCH1122|London|Tom|12B|16
SCH1122|London|Steve|09A|17
SCH1122|London|Joe|13A|15

用于转换XML的代码如下:

private string PerformTransformation(string FilePath)
{
    string fullXsltFile;
    if (chkDateIncrement.Checked == false)
        fullXsltFile = Resources.XSLTTest; // Resources.XSLT;
    else
        fullXsltFile = Resources.XSLTTest;
    XmlDocument xsltTransformDocument = new XmlDocument();
    xsltTransformDocument.LoadXml(fullXsltFile);
    FileInfo xmlFileInfo = new FileInfo(FilePath);
    string outputFile = CreateXmlOutputFileName(xmlFileInfo);
    // load the Xslt with any settings
    XslCompiledTransform transformation = new XslCompiledTransform();
    XsltSettings settings = new XsltSettings(true, false);
    settings.EnableScript = true;
    transformation.Load(xsltTransformDocument, settings, new XmlUrlResolver());
    using (XmlReader reader = XmlReader.Create(FilePath))
    {
       using (FileStream stream = new FileStream(outputFile, FileMode.Create))
       {
           transformation.Transform(reader, null, stream);
           stream.Close();
       }
       reader.Close();
    }
    return outputFile;
}

我也在使用带有VS2010的微软处理器,所以很遗憾不支持v2.0,因此必须是v1.0 XSLT

最好使用标准xslt1.0构建来实现这一点,因为引入额外的组件不是最容易的事情。

XSLT Batch Processing

使用纯XSLT1.0不可能生成多个结果文档

要做到这一点,您需要调用一个扩展函数(您必须编写该函数)来将元素保存在一个单独的文件中。

您需要阅读MSDN文档,了解如何编写扩展函数

转换

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my" exclude-result-prefixes="my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:param name="pBatchLength" select="2"/>
 <xsl:variable name="vId" select="/*/SchoolInfo/SchoolID"/>
 <xsl:variable name="vLoc" select="/*/SchoolInfo/Geographics/Location"/>
 <xsl:template match="/*">
  <xsl:apply-templates select="Pupil[position() mod $pBatchLength = 1]"/>
 </xsl:template>
 <xsl:template match="Pupil">
   <xsl:variable name="vrtfBatch">
    <batch>
      <xsl:apply-templates mode="inbatch" select=
        ". | following-sibling::Pupil[not(position() > $pBatchLength -1)]"/>
    </batch>
   </xsl:variable>
    <xsl:value-of select=
      "my:writeResult($vrtfBatch, ceiling(position() div $pBatchLength))"/>
 </xsl:template>
 <xsl:template match="Pupil" mode="inbatch">
  <xsl:value-of select=
    "concat('&#xA;', $vId, '|', $vLoc, '|', Name, '|', Class, '|', Age)"/>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

解释

  1. "批"的所需长度在外部/全局参数$pBatchLength中指定,其默认值(对于我们的小演示示例,定义为2)。

  2. 将处理所有启动新批处理的Pupil元素(以匿名模式)。

  3. 如有必要,将批处理封装在batch元素中(否则,可能会删除此代码)。然后,在"inbatch"模式下处理包括当前批次的所有Pupil元素,并为它们中的每一个生成必要的CSV输入。

  4. iutput被捕获在一个名为$vrtfBatch的变量中。扩展函数(您必须编写)my:writeResult被调用,参数为:$vrtfBatch和该批次的序列号。扩展函数必须创建一个新文件(使用seq.no作为文件名),并在其中写入内容。

您可以使用可扩展样式表(xslt)来完成此操作。