【问题标题】:XSLT: Reading a param that's an xml document passed as a stringXSLT:读取作为字符串传递的 xml 文档的参数
【发布时间】:2014-05-20 18:16:21
【问题描述】:

我遇到了另一位工程师的问题。作为一名新工程师,我必须找出解决方案,但我一直没能。任何帮助将不胜感激,我找到的最接近的是Chunk string with XSLT,但仍然不完全存在。我只能使用 XSL v1.0。

一个参数作为一个巨大的字符串传递给我的样式表。它最初来自一个 XML 文档。字符串看起来像这样。

<xsl:value-of select="$servers"/> 其中$servers 是传递给我的字符串的参数。字符串如下所示:

<license><active_servers><server><name>MIKE</name><capacity>18</capacity><status>0</status><expiration></expiration><left>0</left><comment></comment></server><server><name>Susie</name><capacity>0</capacity><status>1</status><expiration>2014-07-04T00:00:00Z</expiration><left>5238568</left><comment></comment></server><server><name>Zoe</name><capacity>5000</capacity><status>1</status><expiration></expiration><left>0</left><comment></comment></server></active_servers></license>

这是作为参数传递给样式表的 xml 数据的一部分。实际文档是300行左右的数据。将这些“节点”分开的唯一独特之处是<server></server>。如果它是一个非常大的字符串,有没有办法从中提取数据?

比如说。我需要找到“Zoe”,看看她是否有“到期”,如果没有,我需要她的“状态”。所以 Zoe 将显示“1”作为状态,因为她没有过期时间。而 MIKE 将显示“0”而 Susie 将显示 2014-07-04T00:00:00Z。

我查看了所有的谷歌和堆栈溢出来寻找解析/读取巨大字符串的解决方案。但我还没有找到一个足够接近的解决方案,我可以让它发挥作用。截至目前,我被困在没有工作副本的情况下,并且进行了 2 天的研究却一无所获。

【问题讨论】:

  • 字符串不是 XMl,不能解析为 XML。有没有办法将 path 作为参数传递给实际的 XML 文档?
  • 我 4 天前给另一位工程师发了电子邮件,他在世界各地,但没有收到回音。所以我接受它,这就是他想要的方式。我想也许我错过了一些能够读取这样的字符串的东西。我知道我可以测试某个关键字的字符串,例如 MIKE 或 Zoe,但我认为我不能测试关键字后面的数据,对吗?
  • 您可以使用 XSLT 1.0 提供的字符串函数将字符串 解析为字符串 - 这将非常繁琐且容易出错。您应该真正努力将输入处理 as XML - 这意味着(1)访问 XML 文件中的原始数据;或 (2) 连续进行两次转换,第一次转换将参数保存到具有已知路径的文件中,第二次转换从该文件中读取。
  • 您的第一个解决方案是将参数作为 XML 文档发送,原始数据是我想到的解决方案。我会和工程师多谈谈,看看我能不能改变他的想法。感谢您的帮助和保证,我在正确的轨道上!您能否发布一个答案,我会将其标记为已回答并已关闭。

标签: xml string xslt


【解决方案1】:

字符串不是 XML,不能解析为 XML。您当然可以使用 XSLT 1.0 提供的字符串函数将字符串 解析为字符串 - 这将非常繁琐且容易出错。

如果可能,将 路径 作为参数传递给实际的 XML 文档。或者,串联调用两个转换,第一个转换将参数保存到具有已知路径的文件中,第二个转换从该文件中读取。

另请参阅:
https://stackoverflow.com/a/14512924/3016153

【讨论】:

    【解决方案2】:

    不可能将字符串解析为 XML,正如在接受的答案中正确观察到的 @michael.hor257k,但是 有一种方法可以通过将字符串加载为嵌入文档。这可以使用 data URI schemedocument() 函数。但是,XSLT 1.0 Specification 警告说,这取决于实现(处理器不需要支持任何 uri 方案)。我用 Xalan 和 Saxon 6 等 XSLT 1.0 处理器对此进行了测试,结果很好。

    解决方案是将您的字符串附加到数据 URI 方案 data:text/xml,以逗号分隔。然后,您可以将此字符串传递给您的 document() 函数,它会将其解析为 XML 文件:

    document(concat('data:text/xml,',$servers))
    

    然后您可以将任何模板应用到节点集。

    这是一个带有$servers 参数的样式表,它应该接收包含XML 数据的字符串。它将解析字符串,转换模板中的节点,并生成包含一些数据的 XML 输出:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:output indent="yes"/>
        <xsl:param name="servers"/>
    
        <xsl:template match="/">
            <xsl:apply-templates select="document(concat('data:text/xml,',$servers))/license"/>
        </xsl:template>
        
        <xsl:template match="license">
            <results>
                <xsl:apply-templates/>
            </results>
        </xsl:template>
        
        <!-- server without expiration - get status -->
        <xsl:template match="server[not(string(expiration))]">
            <server name="{name}" status="{status}" />
        </xsl:template>
        
        <!-- server with expiration - get expiration -->
        <xsl:template match="server">
            <server name="{name}" expiration="{expiration}" />
        </xsl:template>
        
    </xsl:stylesheet>
    

    如果您使用任何来源运行此程序,并且您的数据作为参数传递,您将获得:

    <results>
       <server name="MIKE" status="0"/>
       <server name="Susie" expiration="2014-07-04T00:00:00Z"/>
       <server name="Zoe" status="1"/>
    </results>
    

    更新:此功能还依赖于解析器对 data-uris 的支持。我没有意识到这一点,因为我的 XML 环境具有这种支持,因此更改不同的 XSLT 处理器没有任何区别。我在 Mac OS X 环境中使用了 Oxygen XML Editor 15.2。当我确切地发现它正在使用哪个解析器时,我会更新此信息。

    【讨论】:

    • 这是一个有趣的想法,但是我无法在任何处理器上重现您的成功。我同时使用 Saxon 和 Xalan 收到“格式错误的 URL”警告。您能否在此处更正示例:xsltransform.net/bFukv8r
    • @michael.hor257k 似乎它也依赖于解析器的 data-uri 支持。它可以在 Oxygen XML Editor 15.2(和命令行环境,它共享相同的配置)中工作,但我还不能让它与标准的 Java 8 TraX 实现一起工作。
    猜你喜欢
    • 1970-01-01
    • 2019-04-14
    • 1970-01-01
    • 1970-01-01
    • 2012-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多