【问题标题】:XSLT - sneaky insertion(xsl:copy)XSLT - 偷偷插入(xsl:copy)
【发布时间】:2012-09-20 06:20:58
【问题描述】:

我将从代码开始 - 我们都喜欢代码:D

XML:

    <report>
        <subject>
            <subjectId>1</subjectId>
            <name>John</name>
            <surname>Doe</surname>
        </subject>
        <subject>
            <subjectId>2</subjectId>
            <name>Frank</name>
            <surname>Timothy</surname>
        </subject>
        <individual>
            <individualId>10</individualId>
            <name>Isaac</name>
            <surname>Newton</surname>
            <co-worker>
                <subject>
                    <subjectId>1</subjectId>
                    <inXml>true</inXml>
                </subject>
                <subject>
                    <subjectId>2</subjectId>
                    <inXml>true</inXml>
                </subject>
            </co-worker>
        </individual>

        <owner>
            <subject>
                <subjectId>2</subjectId>
                <inXml>true</inXml>
            </subject>
            <share>100</share>
        </owner>

        <individual>
            <individualId>10</individualId>
            <inXml>true</inXml>
        </individual>
    </report>

XML 2:

    <report>
        <owner>
            <individual>
                <individualId>10</individualId>
                <inXml>true</inXml>
            </individual>
        </owner>
        <individual>
            <individualId>2</individualId>
            <name>John</name>
            <surname>Doe</surname>
            <co-worker>
                <individual>
                    <individualId>10</individualId>
                    <inXml>true</inXml>
                </individual>
            </co-worker>
        </individual>
        <individual>
            <individualId>10</individualId>
            <name>Isaac</name>
            <surname>Newton</surname>
            <co-worker>
                <individual>
                    <individualId>2</individualId>
                    <inXml>true</inXml>
                </individual>
            </co-worker>
        </individual>

    </report>

XSLT:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
        <xsl:output method="xml" indent="yes" />

        <xsl:template match="individual[inXml='true']">
            <xsl:variable name="indId" select="./individualId/text()" />
            <xsl:variable name="result" select="//individual[not(inXml) and individualId=$indId]/*" />
            <xsl:choose>
                <xsl:when test="$result != ''">
                    <xsl:copy>
                        <xsl:apply-templates select="$result" />
                    </xsl:copy>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy-of select="." />
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>

        <xsl:template match="subject[inXml='true']">
            <xsl:variable name="subId" select="./subjectId/text()" />
            <xsl:variable name="result" select="//subject[not(inXml) and subjectId=$subId]/*" />
            <xsl:choose>
                <xsl:when test="$result != ''">
                    <xsl:copy>
                        <xsl:apply-templates select="$result" />
                    </xsl:copy>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy-of select="." />
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>

        <xsl:template match="@* | node()">
            <xsl:copy>
                <xsl:apply-templates select="@* | node()" />
            </xsl:copy>
        </xsl:template>

    </xsl:stylesheet>

我想达到什么目的? - 我想在出现“inXml”标签的地方复制主题/个人。 XSLT 似乎可以工作..但是对于稍大的 xmls.. 大约 1MB(它并不大..) 我的 java 应用程序因 java.lang.OutOfMemoryError: Java heap space 而失败。 我将流重定向到文件......令人惊讶的是 - 转换结果的文件以光速增长 - 15秒后大约300mb! :D hehehe - 这证明我的 xlst 中一定有一些错误导致无限循环。

重要的是——在复制节点时,可能会发生内部已经存在“inXml”的情况——这就是我应用模板或结果的原因。我准备的 XML 描述了这个问题。

编辑: XML2 很可能完全搞砸我的应用程序。我该如何解决?我希望通过 XSLT 解决我的 jaxb 解组问题——这不是我知道的解决方案——我需要在解组过程中插入对象的引用,而不是尝试在那里插入更多的 XML 节点。我怎样才能做到这一点?

提前谢谢你!

【问题讨论】:

  • 您帖子中的 xml 和 xsl 适用于我使用 xsltproc 运行。
  • 就像我说的......它在小文件中工作。在大的时候它会崩溃;-/
  • 考虑在转换失败的地方发布一个最小但完整的文件。您是否尝试过增加 Java JRE 允许分配的内存?您使用哪种 Java XSLT 处理器?如果数据结构是递归的并且一次又一次地调用应用模板,那么我也预计会出现堆栈溢出,不一定是内存不足错误。当您转换到一个文件时,您看到结果在增长,您是中止了转换还是在一段时间后完成了?
  • 它没有完成。在“几秒钟”之后,我立即停止了应用程序,文件超过 2gb :D 我为自己感到骄傲.. ]:>

标签: java xml xslt xml-parsing stax


【解决方案1】:

如果您的数据中有循环,您的代码将进入无限递归。

我怀疑条件not(inXml) 应该是not(inXML='true') 以防止这种情况;但不知道你的数据,我不能确定。

【讨论】:

  • 感谢您的回答。 not(inXml) 是来自模式的条件 - 要么有“完整数据 + id”或“inXml + id” - not(inXml='true') 会减慢进程。
  • 我认为 XML2 描述了我的文件中可能发生的循环。我该如何解决这个问题?
  • @MironBe,当我有时间时,我会尝试找到一个可接受的解决方案。很明显,XSLT 2.0 是解决此任务的更好工具,因为它可以不使用临时文档树来获取中间结果,这可以显着提高效率——无论是在内存上还是在时间上。只需进行“实用程序”转换来检查周期就容易多了——您对这样的实用程序和 XSLT 2.0 解决方案感兴趣吗?
  • @Dimitre Novatchev,谢谢你的回答。我需要将 XML 映射到 java 中的对象。当我得到只设置了 inXml 标志的“空”对象时,我认为 XSLT 对我来说是一个解决方案。我不确定 XSLT 是否是我现在真正需要的。我认为我需要对 JAXB 进行更多研究,并找出如何在该级别上解决它。
  • @MironBe,XSLT 非常适合此类问题。 “空对象”是什么意思?一个例子?编辑问题并提供任何此类附加信息是个好主意。
猜你喜欢
  • 1970-01-01
  • 2015-09-07
  • 1970-01-01
  • 1970-01-01
  • 2018-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多