XSLT - 如何正确解析 XHTML 文本
XSLT - How to I correctly parse XHTML text
我正在尝试将一些 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 结构,但我现在很困惑。有什么建议吗?
仅根据一个小示例和没有实现的代码,很难说出您到底想要实现什么。以下对您有用吗?
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>
我正在尝试将一些 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 结构,但我现在很困惑。有什么建议吗?
仅根据一个小示例和没有实现的代码,很难说出您到底想要实现什么。以下对您有用吗?
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>