使用 XSLT 解析多行

发布于 2024-11-08 06:01:35 字数 873 浏览 1 评论 0原文

我有以下节点,需要使用 XSLT 1.0 从 xml 文件解析

<log>Passed -ID:1 -Log:
Passed -ID:2 -Log:Suite
File/Folder
Failed -ID:3 -Log:Suite
Validate Install Failed
Passed -ID:4 -Log:
</log>

这是 -ID: -Log:

如您所见,可以写在一行或多行上。

结果我想得到另一个 xml 文件,其中来自节点的数据将被解析。如果带有 ID 的记录通过了,那么我需要写“/>”。 如果记录失败那么我需要写

<testcase name="<ID Name>">
  <failure message="<Log Message>"/>
</testcase>

换句话说我需要获取这个xml文件。

<xml>
   <testcase name="1"/>
   <testcase name="2"/>
   <testcase name="3">
      <failure message="Suite Validate Install Failed"/>
   </testcase>
   <testcase name="4"/>
</xml>

您认为做到这一点的最佳方法是什么?

xml 文件实际上非常大,我在这里只提供了一个需要解析的节点。我使用 xslt 是因为我从其他节点获取其他信息,结果 xml 文件也需要这些信息。

谢谢。

I have the following node I need to parse using XSLT 1.0 from xml file

<log>Passed -ID:1 -Log:
Passed -ID:2 -Log:Suite
File/Folder
Failed -ID:3 -Log:Suite
Validate Install Failed
Passed -ID:4 -Log:
</log>

Here is the -ID: -Log:

as you can see can be written on one line or on multiple lines.

In result I would like to get another xml file where the data from node will be parsed. If record with ID was Passed then I need to write "/>.
If record was Failed then I need to write

<testcase name="<ID Name>">
  <failure message="<Log Message>"/>
</testcase>

In other words I need to get this xml file.

<xml>
   <testcase name="1"/>
   <testcase name="2"/>
   <testcase name="3">
      <failure message="Suite Validate Install Failed"/>
   </testcase>
   <testcase name="4"/>
</xml>

What do you think can be best way to do this?

The xml file is actually very big and I provided here only one node I need to parse. I'm using xslt because I'm getting other information from other nodes which I also need for result xml files.

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

请持续率性 2024-11-15 06:01:35

XSLT 不是适合此任务的技术。 XSLT 非常擅长转换 XML 文档的结构(通常转换为另一个 XML 文档,但 XML 到文本也是可能的)。 XSLT 不适合解析文本和操作它。

您所拥有的是恰好位于 XML 元素内的一些结构化文本。

我会选择另一种转换技术,正则表达式或简单的字符串解析方法。

XSLT is not the right technology for this task. XSLT is fantastic at transforming the structure of XML documents (typically to another XML document, but XML-to-text is also possible). XSLT is not good for parsing text and manipulating it.

What you have is some structured text that happens to be within an XML element.

I would opt for another transformation technique, Regex, or simple string parsing methods.

单调的奢华 2024-11-15 06:01:35

以下 XSLT 演示了如何仅使用 tokenize() 分割令牌中的 log 内容。 XSLT 2.0 可能有更好的选择(例如 xsl:analyze-string),但由于仅使用 tokenize(),此解决方案也适用于使用 EXSLT 模板扩展的 XSLT 1.0


XSLT 2.0Saxon-B 9.0.0.2J 上测试

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>


    <xsl:template match="/">
        <xml>
            <xsl:variable name="string" select="."/>

            <xsl:variable name="pass" select="tokenize($string,'Passed -ID:')[not(position()=1)]"/>

            <xsl:for-each select="$pass">

                <xsl:choose>
                    <xsl:when test="contains(.,'Failed -ID:')">
                        <xsl:variable name="failure" select="tokenize(.,'Failed -ID:')"/>

                        <xsl:for-each select="$failure">
                            <xsl:choose>
                                <xsl:when   test="position()=1">
                                    <testcase name="{tokenize(.,'\s-Log:')[1]}"/>
                                </xsl:when>
                                <xsl:otherwise>
                                    <xsl:variable name="tc" select="tokenize(.,'\s-Log:')"/>
                                    <testcase name="{$tc[1]}">
                                        <failure message="{$tc[2]}"/>
                                    </testcase>
                                </xsl:otherwise>
                            </xsl:choose>
                        </xsl:for-each>
                    </xsl:when>

                    <xsl:otherwise>
                        <testcase name="{tokenize(.,'\s-Log:')[1]}"/>
                    </xsl:otherwise>

                </xsl:choose>
            </xsl:for-each>
            <xsl:apply-templates/>
        </xml>
    </xsl:template>

    <xsl:template match="log"/>


</xsl:stylesheet>

上述 XSLT 应用于以下输入:

<log>Passed -ID:1 -Log:
Passed -ID:2 -Log:Suite
File/Folder
Failed -ID:3 -Log:Suite
Validate Install Failed
Passed -ID:4 -Log:
Failed -ID:5 -Log:aaaaaa
Failed -ID:6 -Log:dfsfsdf
Failed -ID:7 -Log:dsfsfs
fsdfsdfsdfsdfs
Passed -ID:8 -Log:dfsdfsf
Failed -ID:9 -Log:dfsdfs
</log>

生成以下输出:

<xml>
   <testcase name="1"/>
   <testcase name="2"/>
   <testcase name="3">
      <failure message="Suite
Validate Install Failed
"/>
   </testcase>
   <testcase name="4"/>
   <testcase name="5">
      <failure message="aaaaaa
"/>
   </testcase>
   <testcase name="6">
      <failure message="dfsfsdf
"/>
   </testcase>
   <testcase name="7">
      <failure message="dsfsfs
fsdfsdfsdfsdfs
"/>
   </testcase>
   <testcase name="8"/>
   <testcase name="9">
      <failure message="dfsdfs
"/>
   </testcase>
</xml>

请注意 < /code> 是由于源文本的换行而出现的,因为我们将内容放置在属性值内。为了消除这个问题,最好将消息作为元素 failure 的内容包含在内。无论如何,下面的文章处理棘手的空间。

The following XSLT demonstrates how to split log content in tokens just using tokenize(). There are probably better choices with XSLT 2.0 (for example xsl:analyze-string), but because of using tokenize() only, this solution is applicable also to XSLT 1.0 extended with EXSLT templates.


XSLT 2.0 tested on Saxon-B 9.0.0.2J

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>


    <xsl:template match="/">
        <xml>
            <xsl:variable name="string" select="."/>

            <xsl:variable name="pass" select="tokenize($string,'Passed -ID:')[not(position()=1)]"/>

            <xsl:for-each select="$pass">

                <xsl:choose>
                    <xsl:when test="contains(.,'Failed -ID:')">
                        <xsl:variable name="failure" select="tokenize(.,'Failed -ID:')"/>

                        <xsl:for-each select="$failure">
                            <xsl:choose>
                                <xsl:when   test="position()=1">
                                    <testcase name="{tokenize(.,'\s-Log:')[1]}"/>
                                </xsl:when>
                                <xsl:otherwise>
                                    <xsl:variable name="tc" select="tokenize(.,'\s-Log:')"/>
                                    <testcase name="{$tc[1]}">
                                        <failure message="{$tc[2]}"/>
                                    </testcase>
                                </xsl:otherwise>
                            </xsl:choose>
                        </xsl:for-each>
                    </xsl:when>

                    <xsl:otherwise>
                        <testcase name="{tokenize(.,'\s-Log:')[1]}"/>
                    </xsl:otherwise>

                </xsl:choose>
            </xsl:for-each>
            <xsl:apply-templates/>
        </xml>
    </xsl:template>

    <xsl:template match="log"/>


</xsl:stylesheet>

The above XSLT applied on the following input:

<log>Passed -ID:1 -Log:
Passed -ID:2 -Log:Suite
File/Folder
Failed -ID:3 -Log:Suite
Validate Install Failed
Passed -ID:4 -Log:
Failed -ID:5 -Log:aaaaaa
Failed -ID:6 -Log:dfsfsdf
Failed -ID:7 -Log:dsfsfs
fsdfsdfsdfsdfs
Passed -ID:8 -Log:dfsdfsf
Failed -ID:9 -Log:dfsdfs
</log>

Produces the following output:

<xml>
   <testcase name="1"/>
   <testcase name="2"/>
   <testcase name="3">
      <failure message="Suite
Validate Install Failed
"/>
   </testcase>
   <testcase name="4"/>
   <testcase name="5">
      <failure message="aaaaaa
"/>
   </testcase>
   <testcase name="6">
      <failure message="dfsfsdf
"/>
   </testcase>
   <testcase name="7">
      <failure message="dsfsfs
fsdfsdfsdfsdfs
"/>
   </testcase>
   <testcase name="8"/>
   <testcase name="9">
      <failure message="dfsdfs
"/>
   </testcase>
</xml>

Note that is due to line-feeds of the source text appearing because we are placing the content inside the attribute value. To get rid of that it would be better to include the message as content of the element failure. Anyway the following article deals with tricky spaces.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文