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

标签 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 中。

最佳答案

合并 XML 文档并转换

在 XLS 转换之前,您必须做一些工作来合并 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 文档的内容合并在一起,并将其传递以进行转换。

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 的快捷方式。

关于ruby - 使用多个源 XML 文件的 Nokogiri XSLT 转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38505529/

相关文章:

ruby-on-rails - Selenium Webdriver ruby​​ 升级(write_timeout 错误)

ruby - ruby 有 global_variable_set 吗?

java - XMLBeans inst2xsd 内存不足错误

Javascript 比另一个属性上的 XSLT generate-id() 更好地识别回调节点

ruby - Ruby 中的命名空间要求

ruby - Object#respond_to 如何?工作?

Android:来自 xml 布局的自定义 View

C# XML 序列化排除写类名

xslt - Nokogiri (Ruby) 和 XPath

xml - XSL : List divided into columns