【问题标题】:XSLT Batch ProcessingXSLT 批处理
【发布时间】:2012-03-09 11:35:07
【问题描述】:

我有以下 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 构建来执行此操作,因为添加其他组件并不是最简单的事情。

【问题讨论】:

  • 请提供所需的确切结果。此外,不是每个人都能猜测 PSV 的含义——我目前的猜测是“管道分隔值”。请编辑问题并提供必要的信息。
  • 当然,XSLT 是“程序化的”:)
  • 我之后能够批量处理数据(例如 400 个学生,只有 50 个 .txt 文件,所以制作 8 个文件)而不是你给出的实际输出结构,正如我所说在示例 XML 下方的段落中。
  • 问题中没有提及创建不同的文件。请编辑问题并添加此缺失的要求。此外,在纯 XSLT 1.0 中创建多个输出文件是不可能的。您将需要一个 XSLT 2.0 处理器,或者一个具有exslt:document 扩展元素的 EXSLT 实现的 XSLT 处理器,或者您需要编写自己的扩展函数。请在问题中说明您需要哪些可能的解决方案。
  • 按要求编辑,更喜欢扩展功能

标签: c# xml xslt batch-processing


【解决方案1】:

纯 XSLT 1.0 不可能生成多个结果文档

为此,您需要调用扩展函数(您必须编写该函数)以将元素保存在单独的文件中。

您需要阅读您在 how to write an extension function 上的 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 作为文件名)并在其中写入内容。

【讨论】:

  • 你能解释一下这里发生的事情背后的逻辑吗?
【解决方案2】:

您可以使用eXtensible Stylesheets (xslt) 执行此操作。

【讨论】:

  • 您是否知道 Microsoft 的重定向命名空间,因为它是为特定处理器编写的
  • 其实在msxml中并没有直接类似于“redirect”的东西,但是你可以写一个Javascript方法,它接受一个result-tree-fragment作为参数,并使用微软提供的方法序列化它DOM 实现。
  • 遗憾的是,我对 javascript 一无所知,因此无法排除这一点
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-29
  • 2010-12-17
  • 2019-08-22
  • 2011-06-04
  • 2021-11-08
  • 2012-05-18
  • 1970-01-01
相关资源
最近更新 更多