1

我想做以下事情:此时我们收到一些 xml 文件,其中一些 xml 标记被错误地填充。为了帮助我们的合作伙伴,我们希望通过使用“Pass-through”文件夹来捕获这些错误值,在导入我们的应用程序之前,所有 xml 文件都放置在该文件夹中。

该文件夹将每 X 分钟读取一次,并且对于每个文件都需要进行一些检查,例如:标签中值的长度、标签的值等。

因为这只是一个临时解决方案,我们不想在我们的应用程序中实现它。

我在考虑两种可能的设置:

  • 使用 java 并调用 XSLT 文件来转换每个文件并将其放在另一个文件夹中
  • 仅使用 java 检查 xml 文件并进行转换。这两种情况都将由每 X 分钟运行一次的 .bat 调用。

现在我的问题:

  • 您认为最好的解决方案是什么?又名最快、最安全等(可能不是建议的?)
  • 你能不能给我一些例子来说明如何做这样的事情?

我不像其他严格要求代码的人。如果你能给我类似的东西,我可以自己做。在写这篇文章的时候,我已经在其他网站上寻找解决方案了,但是因为很紧急,问问社区也是有帮助的。

谢谢你的回答,亲切的问候,马丁

编辑:这两个答案对我帮助很大。谢谢你们。

4

2 回答 2

1

如果您想使用 .bat 脚本在给定文件夹中的每个 XML 文件上运行 XSLT(您在 OP 中的第一个选项),我可以想到 3 种方法:


A.基本上做一个“for”循环来通过命令行处理每个单独的文件。(哇。)


B.用于collection()指向输入文件夹并用于xsl:result-document在新文件夹中创建输出文件。

这是一个示例 XSLT 2.0(使用 Saxon 9 测试):

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:param name="pInputDir" select="'input'"/>
  <xsl:param name="pOutputDir" select="'output'"/>
  <xsl:variable name="vCollection" select="collection(concat($pInputDir,'/?*.xml'))"/>

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/">
    <xsl:for-each select="$vCollection">
      <xsl:variable name="vOutFile" select="tokenize(document-uri(document(.)),'/')[last()]"/>
      <xsl:result-document href="{concat($pOutputDir,'/',$vOutFile)}">
        <xsl:apply-templates/>   
      </xsl:result-document>
    </xsl:for-each>    
  </xsl:template>

</xsl:stylesheet>

笔记:

这个样式表只是做一个身份转换。它通过未更改的方式传递 XML。您需要通过添加新模板来覆盖身份模板来进行检查/更改。

另请注意,输入和输出文件夹名称有 2 个参数。

您可能会遇到内存问题,collection()因为它将文件夹中的所有 XML 文件加载到内存中。如果这是一个问题,请参见下文...


C.让您的 XSLT 处理目录中所有文件的列表。使用组合document()和 Saxon 扩展函数saxon:discard-document()来加载和丢弃文档。

这是我不久前用于测试的一个示例。

XML 文件列表(XSLT 的输入):

<files>
  <file>file:///C:/input_xml/file1.xml</file>
  <file>file:///C:/input_xml/file2.xml</file>
  <file>file:///C:/input_xml/file3.xml</file>
  <file>file:///C:/input_xml/file4.xml</file>
  <file>file:///C:/input_xml/file5.xml</file>
  <file>file:///C:/input_xml/file6.xml</file>
  <file>file:///C:/input_xml/file7.xml</file>
  <file>file:///C:/input_xml/file8.xml</file>
  <file>file:///C:/input_xml/file9.xml</file>
  <file>file:///C:/input_xml/file10.xml</file>
</files>

XSLT 2.0(用 Saxon 9 测试):

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:param name="pOutputDir" select="'output'"/>

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="files">
    <xsl:apply-templates/>      
  </xsl:template>

  <xsl:template match="file">
    <xsl:variable name="vOutFile" select="tokenize(document-uri(document(.)),'/')[last()]"/>
    <xsl:result-document href="{concat($pOutputDir,$vOutFile)}">
      <xsl:apply-templates select="document(.)/saxon:discard-document(.)" xmlns:saxon="http://saxon.sf.net/"/>          
    </xsl:result-document>
  </xsl:template>

</xsl:stylesheet>

笔记:

同样,此样式表只是进行身份转换。它通过未更改的方式传递 XML。您需要通过添加新模板来覆盖身份模板来进行检查/更改。

另请注意,输出文件夹名称只有一个参数。

于 2012-04-06T07:32:40.933 回答