这与我几个月前提出的问题相反。我有一个嵌套的结构,我需要展平。例如,输入可能是这样的:
<root>
<h1>text</h1>
<ol>
<li>num1</li>
<li>num2
<ol>
<li>sub-num1</li>
<li>sub-num2
<ol>
<li>sub-sub-num1</li>
</ol>
</li>
</ol>
</li>
<li>num3</li>
</ol>
<p>text</p>
<ol>
<li>num1</li>
<li>num2</li>
</ol>
<h2>text</h2>
</root>
输出应该按如下方式展平:
<root>
<h1>text</h1>
<list level="1">num1</list>
<list level="1">num2</list>
<list level="2">sub-num1</list>
<list level="2">sub-num2</list>
<list level="3">sub-sub-num1</list>
<list level="1">num3</list>
<p>text</p>
<list level="1">num1</list>
<list level="1">num2</list>
<h2>text</h2>
</root>
我想我可以用一种不优雅的方式做到这一点,但我希望有人可能有更好的方法来分享。这需要使用XSLT 1.0
完成答案 0 :(得分:4)
此样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ol">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="li">
<list level="{count(ancestor::ol)}">
<xsl:apply-templates select="node()[not(self::ol)]"/>
</list>
<xsl:apply-templates select="ol"/>
</xsl:template>
</xsl:stylesheet>
输出:
<root>
<h1>text</h1>
<list level="1">num1</list>
<list level="1">num2
</list>
<list level="2">sub-num1</list>
<list level="2">sub-num2
</list>
<list level="3">sub-sub-num1</list>
<list level="1">num3</list>
<p>text</p>
<list level="1">num1</list>
<list level="1">num2</list>
<h2>text</h2>
</root>
答案 1 :(得分:2)
使用Oxygen / XML和您的输入进行测试。如果嵌套的OL在之前和之后都有文本,则没有指定您想要发生的内容;在这种情况下,所有文本都将在嵌套项之前输出。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
exclude-result-prefixes="xs xd"
version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ol">
<xsl:param name="level" as="xs:integer" select="0"/>
<xsl:apply-templates select="li">
<xsl:with-param name="level" select="$level+1"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="li">
<xsl:param name="level" as="xs:integer"/>
<list level="{$level}"><xsl:value-of select="normalize-space(string-join(text(),' '))"/></list>
<xsl:apply-templates select="ol">
<xsl:with-param name="level" select="$level"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:1)
XSLT 1.0 解决方案:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ol">
<xsl:apply-templates select="@* | node()"/>
</xsl:template>
<xsl:template match="li">
<list level="{count(ancestor::li) + 1}">
<xsl:value-of select="text()"/>
</list>
<xsl:apply-templates select="*"/>
</xsl:template>
</xsl:stylesheet>
针对您的样本的正确结果是:
<root>
<h1>text</h1>
<list level="1">num1</list>
<list level="1">num2</list>
<list level="2">sub-num1</list>
<list level="2">sub-num2</list>
<list level="3">sub-sub-num1</list>
<list level="1">num3</list>
<p>text</p>
<list level="1">num1</list>
<list level="1">num2</list>
<h2>text</h2>
</root>
答案 3 :(得分:0)
谢谢Jim,你让我走上正轨。我稍微修改了样式表,因为我需要在<li>
元素中应用模板。我还删除了level参数,因为这个值可以通过计算祖先来获得。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" exclude-result-prefixes="xs xd" version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ol">
<xsl:if test="not(ancestor::ol)">
<xsl:apply-templates/>
</xsl:if>
</xsl:template>
<xsl:template match="li">
<list level="{count(ancestor::ol)}">
<xsl:apply-templates/>
</list>
<xsl:apply-templates select="ol" mode="passThrough"/>
</xsl:template>
<xsl:template match="ol" mode="passThrough">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>