【问题标题】:Analyse XML file for mixed content assuming no XSD/Schema file available假设没有可用的 XSD/Schema 文件,分析 XML 文件中的混合内容
【发布时间】:2020-02-26 05:02:46
【问题描述】:
一个简单的问题,但我似乎无法在任何地方找到答案...... perl(或者可能是命令行工具)中是否有任何现有方法来检查给定的 XML 文件是否包含混合内容?
我只需要一些东西来告诉我是否存在混合内容。尽管如果发现混合内容的任何细节将是一个奖励。如果存在任何东西,那么处理文件而不将其完全加载到内存中也会更好,因为我需要分析的文件是 100 MB,甚至在某些情况下是几 GB。如果什么都不存在,那么我将开始考虑自己写一些东西。
以上所有内容都假定 XSD/Schema 文件不适用于给定的 XML 文件。
【问题讨论】:
标签:
xml
perl
mixed-content
【解决方案1】:
XPath 查询 boolean(//*[text()[normalize-space()] and *]) 如果有一个元素同时具有元素和非空白文本子级,则返回 true。
对于流式算法,您需要一个堆栈;在堆栈的每一层,您都需要跟踪是否在该层遇到了非空白文本子级和/或元素子级。使用类似 SAX 的 API 实现起来并不难,虽然我不知道在 Perl 中从哪里开始。
使用 XSLT 3.0 流,我认为可以使用 xsl:iterate:
<xsl:mode streamable="yes"/>
<xsl:template match="*">
<xsl:iterate select="node()">
<xsl:param name="found-element" select="false()"/>
<xsl:param name="found-text" select="false()"/>
<xsl:on-completion>
<xsl:if test="$found-element and $found-text">
<out>Found mixed content!!</out>
</xsl:if>
</xsl:on-completion>
<xsl:apply-templates select="."/>
<xsl:next-iteration>
<xsl:with-param name="found-element" select="$found-element or self::*"/>
<xsl:with-param name="found-text" select="$found-text or self::text()[normalize-space()]"/>
</xsl:next-iteration>
<xsl:iterate>
</xsl:template>
这方面还有很大的改进空间;目前,如果有很多混合内容,它会给你很多消息。