检查某些值的xml标记并进行转换 - 最佳实践

时间:2012-04-05 23:30:50

标签: java xml xslt batch-processing

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

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

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

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

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

现在我的问题:

  • 您认为这是最佳解决方案? a.k.a.最快,最安全等等(也许是建议以外的东西?)
  • 你能否提供一些方法来做这样的事情?

我不像其他严格要求代码的人。如果你能给我类似的东西,我可以自己做。 在撰写本文时,我已经在其他网站上寻找解决方案,但由于它很紧急,所以向社区提问也很有帮助。

感谢您的回答, 亲切的问候, 马腾

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

2 个答案:

答案 0 :(得分:1)

答案 1 :(得分:1)

如果你想使用.bat脚本在给定文件夹中的每个XML文件(OP中的第一个选项)上运行XSLT,我可以想到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保持不变。您需要通过添加新模板来覆盖标识模板以执行检查/更改。

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