使用多个源XML文件的Nokogiri XSLT转换

时间:2016-07-21 13:24:48

标签: ruby xml xslt nokogiri

我想使用Nokogiri翻译XML。我构建了一个XSL,一切正常。我也在Intellij中测试过它。我的数据来自两个XML文件。

当我试图让Nokogiri进行转换时,我的问题就出现了。我似乎无法找到解析多个源文件的方法。

这是我在文档中使用的代码:

require 'Nokogiri'

doc1 = Nokogiri::XML(File.read('F:/transcoder/xslt_repo/core_xml.xml',))
xslt = Nokogiri::XSLT(File.read('F:/transcoder/xslt_repo/google.xsl'))

puts xslt.transform(doc1)

我试过了:

require 'Nokogiri'

doc1 = Nokogiri::XML(File.read('F:/transcoder/xslt_repo/core_xml.xml',))
doc2 = Nokogiri::XML(File.read('F:/transcoder/xslt_repo/file_data.xml',))
xslt = Nokogiri::XSLT(File.read('F:/transcoder/xslt_repo/test.xsl'))

puts xslt.transform(doc1,doc2)

然而似乎transform只接受一个参数,所以目前我只能解析我需要的一半数据:

<?xml version="1.0"?>
<package package_id="LB000001">
  <asset_metadata>
    <series_title>test asset 1</series_title>
    <season_title>Number 1</season_title>
    <episode_title>ET 1</episode_title>
    <episode_number>1</episode_number>
    <license_start_date>21-07-2016</license_start_date>
    <license_end_date>31-07-2016</license_end_date>
    <rating>15</rating>
    <synopsis>This is a test asset</synopsis>
  </asset_metadata>
  <video_file>
    <file_name/>
    <file_size/>
    <check_sum/>
  </video_file>
  <image_1>
    <file_name/>
    <file_size/>
    <check_sum/>
  </image_1>
</package>

我怎样才能让它发挥作用?

编辑:

这是通过PHP代码块创建的core_metadata.xml,数据来自数据库。

<?xml version="1.0" encoding="utf-8"?>
<manifest task_id="00000000373">
  <asset_metadata>
    <material_id>LB111111</material_id>
    <series_title>This is a test</series_title>
    <season_title>This is a test</season_title>
    <season_number>1</season_number>
    <episode_title>that test</episode_title>
    <episode_number>2</episode_number>
    <start_date>23-08-2016</start_date>
    <end_date>31-08-2016</end_date>
    <ratings>15</ratings>
    <synopsis>this is a test</synopsis>
  </asset_metadata>
  <file_info>
    <source_filename>LB111111</source_filename>
    <number_of_segments>2</number_of_segments>
    <segment_1 seg_1_start="00:00:10.000" seg_1_dur="00:01:00.000"/>
    <segment_2 seg_2_start="00:02:00.000" seg_2_dur="00:05:00.000"/>
<conform_profile definition="hd" aspect_ratio="16f16">ffmpeg -i S_PATH/F_NAME.mp4 SEG_CONFORM 2&gt; F:/Transcoder/logs/transcode_logs/LOG_FILE.txt</conform_profile>
<transcode_profile profile_name="xbox" package_type="tar">ffmpeg -f concat -i T_PATH/CONFORM_LIST TRC_PATH/F_NAME.mp4 2&gt; F:/Transcoder/logs/transcode_logs/LOG_FILE.txt</transcode_profile>
    <target_path>F:/profiles/xbox</target_path>
  </file_info>
</manifest>

第二个XML(file_date.xml)是在nokogiri的转码过程中动态创建的:

<?xml version="1.0"?>
<file_data>
  <video_file>
    <file_name>LB111111_xbox_230816114438.mp4</file_name>
    <file_size>141959922</file_size>
    <md5_checksum>bac7670e55c0694059d3742285079cbf</md5_checksum>
  </video_file>
  <image_1>
    <file_name>test</file_name>
    <file_size>test</file_size>
    <md5_checksum>test</md5_checksum>
  </image_1>
</file_data>

我设法通过将file_date.xml硬编码到XSLT文件中来调用此问题:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
    <package>
        <xsl:attribute name="package_id">
            <xsl:value-of select="manifest/asset_metadata/material_id"/>
        </xsl:attribute>
        <asset_metadata>
            <series_title>
                <xsl:value-of select="manifest/asset_metadata/series_title"/>
            </series_title>
            <season_title>
                <xsl:value-of select="manifest/asset_metadata/season_title"/>
            </season_title>
            <episode_title>
                <xsl:value-of select="manifest/asset_metadata/episode_title"/>
            </episode_title>
            <episode_number>
                <xsl:value-of select="manifest/asset_metadata/episode_number"/>
            </episode_number>
            <license_start_date>
                <xsl:value-of select="manifest/asset_metadata/start_date"/>
            </license_start_date>
            <license_end_date>
                <xsl:value-of select="manifest/asset_metadata/end_date"/>
            </license_end_date>
            <rating>
                <xsl:value-of select="manifest/asset_metadata/ratings"/>
            </rating>
            <synopsis>
                <xsl:value-of select="manifest/asset_metadata/synopsis"/>
            </synopsis>
        </asset_metadata>
        <video_file>
            <file_name>
                <xsl:value-of select="document('file_data.xml')/file_data/video_file/file_name"/>
            </file_name>
            <file_size>
                <xsl:value-of select="document('file_data.xml')/file_data/video_file/file_size"/>
            </file_size>
            <check_sum>
                <xsl:value-of select="document('file_data.xml')/file_data/video_file/md5_checksum"/>
            </check_sum>
        </video_file>
        <image_1>
            <file_name>
                <xsl:value-of select="document('file_data.xml')/file_data/image_1/file_name"/>
            </file_name>
            <file_size>
                <xsl:value-of select="document('file_data.xml')/file_data/image_1/file_size"/>
            </file_size>
            <check_sum>
                <xsl:value-of select="document('file_data.xml')/file_data/image_1/md5_checksum"/>
            </check_sum>
        </image_1>
    </package>
</xsl:template>

然后我使用Saxon进行转换:

xslt = "java -jar C:/SaxonHE9-7-0-7J/saxon9he.jar #{temp}core_metadata.xml #{temp}#{profile}.xsl > #{temp}#{file_name}.xml"

system("#{xslt}")

我很想找到一种方法来做到这一点,而无需将file_date.xml硬编码到XSLT中。

1 个答案:

答案 0 :(得分:4)

合并XML文档和转换

您必须做一些工作才能在XLS-Transformation之前组合XML内容。 @ the-Tin-Man有一个很好的answer to a similar question in the archives,可以根据你的使用情况进行调整。

我们假设我们有以下示例内容:

<!--a.xml-->
<?xml version="1.0"?>
<xml>
  <packages>
    <package>Data here for A</package>
    <package>Another Package</package>  
  </packages>
</xml>
<!--a.xml-->

<!--b.xml-->
<?xml version="1.0"?>
<xml>
  <packages>
    <package>B something something</package>  
  </packages>
</xml>
<!--end b.xml-->

我们想要应用以下XLST模板:

<!--transform.xslt-->
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="//packages">
  <html>
  <body>
    <h2>Packages</h2>
    <ol>
      <xsl:for-each select="./package">
        <li><xsl:value-of select="text()"/></li>
      </xsl:for-each>
    </ol>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>
<!--end transform.xslt-->

如果我们有并行文档结构,就像在这种情况下,我们可以合并两个XML文档&#39;将这些内容融合在一起,并将其传递给转型。

require 'Nokogiri'

doc1 = Nokogiri::XML(File.read('./a.xml'))
doc2 = Nokogiri::XML(File.read('./b.xml'))

moved_packages = doc2.search('package')
doc1.at('/descendant::packages[1]').add_child(moved_packages)

xslt = Nokogiri::XSLT(File.read('./transform.xslt'))

puts xslt.transform(doc1)

这会产生以下输出:

<html><body>
<h2>Packages</h2>
<ol>
<li>Data here for A</li>
<li>Another Package</li>
<li>B something something</li>
</ol>
</body></html>

如果您的XML文档具有不同的结构,您可以从添加内容的中间XML节点集中受益,而不是将文档2内容合并到文档1中的快捷方式。