【问题标题】:XSLT - How to I correctly parse XHTML textXSLT - 如何正确解析 XHTML 文本
【发布时间】:2015-02-03 14:02:14
【问题描述】:

我正在尝试将一些 HTML(当然是 XHTML!)文档解析为 XML,以便以后可以将它们处理为其他文档格式。我已经能够递归解析节点树以提取节点和属性信息,但它不能很好地处理实际文本。

这是我的示例来源:

<div>
    <p>
        <a href='http://google.com'>Text in A</a>
    </p>
    <p>Text in P</p>
    <p>How to <strong>emphasise</strong> text</p>
</div>

我希望它产生这样的东西:

<div-tag>
    <id>first</id>
    <p-tag>
        <a-tag>
            <text>Text in A</text>
            <link>http://google.com</link>
        </a-tag>
    <p-tag>
    <p-tag>
        <text>Text in P</text>
    </p-tag>
    <p-tag>
        <text>How to</text>
    </p-tag>
    <strong-tag>
        <text>emphasise</text>
    </strong-tag>
    <p-tag>
        <text>text</text>
    </p-tag>
</div-tag>

我正在使用应用模板递归遍历树:

<xsl:template match="*">
<xsl:variable name="node-name" select="concat(local-name(),'-tag')"/>
<xsl:element name="{$node-name}">
    <xsl:choose>
        <xsl:when test="count(child::*) = 0">
            <xsl:if test="text()">
                <xsl:element name="text"><xsl:value-of select="text()"/></xsl:element>
                <xsl:if test="@href">
                    <xsl:element name="link"><xsl:value-of select="@href"/></xsl:element>
                </xsl:if>
            </xsl:if>
        </xsl:when>
        <xsl:otherwise>
            <xsl:apply-templates select="child::*"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:element>

它最终会丢失一些文本,其中一个节点有文本和子节点,尤其是嵌套的子节点(在我的示例中)。如果我将它设置为在找到任何文本时输出文本(而不仅仅是在没有子节点时),它最终也会显示子节点的文本。

通读这里的问题和答案,我找到了正确解析文本的方法...

<xsl:template match="div//text()">
    <xsl:variable name="node-name" select="concat(local-name(..),'-tag')"/>
    <xsl:element name="{$node-name}">
        <text">
            <xsl:value-of select="normalize-space()" />
        </text>
    </xsl:element>
</xsl:template>

...但它当然不会选择没有文本的节点。它错过了第一个 p 节点,因为它本身没有任何文本。 (我意识到在分割段落时我需要小心处理段落,如上所述,但这是明天的问题!

我确信一定有一种方法可以将 HTML 解析为更简单的 XML 结构,但我现在很困惑。有什么建议吗?

【问题讨论】:

    标签: xml xslt xhtml


    【解决方案1】:

    仅基于一个小示例和没有的代码,很难说出您到底想要实现什么。以下内容对您有用吗?

    XSLT 1.0

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:template match="*">
        <xsl:element name="{local-name()}-tag">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>
    
    <xsl:template match="@href">
        <link>
            <xsl:value-of select="."/>
        </link>
    </xsl:template>
    
    <xsl:template match="text()">
        <text>
            <xsl:copy-of select="."/>
        </text>
    </xsl:template>
    
    </xsl:stylesheet>
    

    【讨论】:

    • 首先 - 为我糟糕的例子道歉。下次我会尽量让它们更完整。其次——是的!这确实有效。非常感谢。我只是想弄清楚它,但如果我理解正确,apply-templates 设置为解析属性和节点,然后您设置了 href 和 text 的捕获。我想我可以扩展它来完成我所需要的一切。再次感谢,迈克尔。它使我对 XSLT 的理解提高了一个档次。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多