Suppose I have a nested HTML list:
假设我有一个嵌套的HTML列表:
<ul>
<li> First Item </li>
<li> Nested list:
<ol>
<li> One </li>
<li> Two </li>
</ol>
</li>
<li> Third Item </li>
</ul>
Is it at all possible to flatten this into a line-by-line representation, where the nesting depth becomes an attribute value? Something like this:
是否可以将其展平为逐行表示,其中嵌套深度成为属性值?像这样的东西:
<line nest="1"> First Item </line>
<line nest="1"> Nested list: </line>
<line nest="2"> One </line>
<line nest="2"> Two </line>
<line nest="1"> Third Item </line>
I just can think of a way of doing this for deeply nested lists. What I have is the following:
我只想到一种为深层嵌套列表执行此操作的方法。我所拥有的是以下内容:
<xsl:template match="ol | ul">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="li">
<line>
<xsl:attribute name="nest"><xsl:value-of select="count(ancestor::ol|ancestor::up)" /></xsl:attribute>
<xsl:apply-templates/>
</line>
</xsl:template>
But this nests the <line>
elements too, and it does not handle other elements like <em>
text inside of a list element.
但是这也会嵌套
2 个解决方案
#1
I would suggest you try it this way:
我建议你这样试试:
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="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/ul">
<root>
<xsl:apply-templates/>
</root>
</xsl:template>
<xsl:template match="li">
<line nest="{count(ancestor::ol|ancestor::ul)}">
<xsl:apply-templates select="node()[not(self::ol or self::ul)]"/>
</line>
<xsl:apply-templates select="ol | ul"/>
</xsl:template>
<xsl:template match="ol | ul">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
This will preserve any HTML markup you might have within a li
element.
这将保留您在li元素中可能具有的任何HTML标记。
#2
You need to move the xsl:apply-templates
after the creation of the line
elements, and change it to select non-text nodes. Inside the line
element you then replace it with an xsl:value-of
to get just the text.
您需要在创建线元素后移动xsl:apply-templates,并将其更改为选择非文本节点。在line元素中,然后用xsl:value-of替换它以获取文本。
Try this XSLT
试试这个XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="ol | ul">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="li">
<line nest="{count(ancestor::ol|ancestor::up)}">
<xsl:value-of select="normalize-space(text())"/>
</line>
<xsl:apply-templates select="node()[not(self::text())]" />
</xsl:template>
</xsl:stylesheet>
Note the use of Attribute Value Templates in the creation of the nest
attribute, to simplify the code.
注意在创建nest属性时使用属性值模板,以简化代码。
#1
I would suggest you try it this way:
我建议你这样试试:
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="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/ul">
<root>
<xsl:apply-templates/>
</root>
</xsl:template>
<xsl:template match="li">
<line nest="{count(ancestor::ol|ancestor::ul)}">
<xsl:apply-templates select="node()[not(self::ol or self::ul)]"/>
</line>
<xsl:apply-templates select="ol | ul"/>
</xsl:template>
<xsl:template match="ol | ul">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
This will preserve any HTML markup you might have within a li
element.
这将保留您在li元素中可能具有的任何HTML标记。
#2
You need to move the xsl:apply-templates
after the creation of the line
elements, and change it to select non-text nodes. Inside the line
element you then replace it with an xsl:value-of
to get just the text.
您需要在创建线元素后移动xsl:apply-templates,并将其更改为选择非文本节点。在line元素中,然后用xsl:value-of替换它以获取文本。
Try this XSLT
试试这个XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="ol | ul">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="li">
<line nest="{count(ancestor::ol|ancestor::up)}">
<xsl:value-of select="normalize-space(text())"/>
</line>
<xsl:apply-templates select="node()[not(self::text())]" />
</xsl:template>
</xsl:stylesheet>
Note the use of Attribute Value Templates in the creation of the nest
attribute, to simplify the code.
注意在创建nest属性时使用属性值模板,以简化代码。