XSLT:读取一个以字符串形式传递的xml文档的参数

时间:2014-05-20 18:16:22

标签: xml string xslt

我遇到了另一位工程师的问题。作为一名新工程师,我必须找到解决方案,但我还没能做到。任何帮助将不胜感激,我发现的最接近的事情是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行左右的数据。区分这些&#34;节点的唯一区别是&#34;是<server></server>。如果它是一个非常大的字符串,有没有办法从中提取数据?

比如说。我需要找到&#34; Zoe&#34;并且看看她是否有过期&#34;如果她没有,我需要她&#34;状态&#34;。所以Zoe将展示&#34; 1&#34;状态,因为她没有到期。而MIKE将显示&#34; 0&#34;和Susie将展出2014-07-04T00:00:00Z。

我已经遍布google和堆栈溢出来寻找解析/读取巨型字符串的解决方案。但我还没有达到足够接近的解决方案,我可以让它发挥作用。截至目前,我没有工作副本,也没有任何地方进行研究2天。

2 个答案:

答案 0 :(得分:3)

无法将字符串解析为XML,正如@ michael.hor257k在接受的答案中正确观察到的那样,但 是一种将字符串视为节点集的方法通过将其加载为嵌入式文档。使用带有document()函数的data URI scheme即可。但是,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。当我发现它正在使用哪个解析器时,我将更新此信息。

答案 1 :(得分:2)

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

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

另见:
https://stackoverflow.com/a/14512924/3016153