XSLT - 分组并丢失 parent 的文本
XSLT - grouping and lost parent's text
我遇到一个问题,当我尝试将代码行分组到块中时,我的 parent 的文本丢失了,我不知道为什么。
XML
<body>
<ul>
<li>before
<filepath>one test</filepath> now some code:
<codeblock>1</codeblock>
<codeblock>2</codeblock>
after text</li>
</ul>
<section>
<title>Test2</title>
<p>qqqq</p>
<codeblock>1</codeblock>
<codeblock>2</codeblock>
<codeblock>3</codeblock>
</section>
</body>
XSLT
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:template match="@*|node()">
<xsl:choose>
<xsl:when test="./codeblock[1] or ./msgblock[1]">
<xsl:call-template name="merge-codeblock">
<xsl:with-param name="container" select="."/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="merge-codeblock">
<xsl:param name="container"/>
<xsl:copy>
<xsl:for-each-group select="*" group-adjacent="boolean(self::codeblock or self::msgblock)">
<xsl:choose>
<xsl:when test="current-grouping-key() and count(current-group()) gt 1">
<xsl:element name="{name()}">
<xsl:variable name="name" select="current-group()/node()" />
<xsl:for-each select="current-group()/node()">
<xsl:variable name="namee" select="current()" />
<xsl:apply-templates select="current()" />
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当前结果
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE task PUBLIC "-//OASIS//DTD DITA Task//EN" "dtd/task.dtd"><!--<!DOCTYPE task PUBLIC "-//OASIS//DTD DITA Task//EN" "dtd/task.dtd">--><body>
<ul>
<li><!-- not ok! I lost my li/text() -->
<filepath>one test</filepath>
<codeblock>1
2
</codeblock>
</li>
</ul>
<section>
<title>Test</title>
<p>fddsfsd</p>
<codeblock>fdsfds</codeblock>
</section>
<section>
<title>Test2</title>
<p>qqqq</p>
<codeblock>1
2
3
</codeblock>
</section>
</body>
我已经尝试将 |text()
添加到我的组选择器中,这解决了问题,但是我的 codeblock
元素不再合并。
我做错了什么?
编辑:
Martin 的回答解决了 LI 问题,但不幸的是,我现在在代码块行之前有额外的 spaces,在第一个代码块之后有一个回车 return:
<codeblock>
1
2
3
</codeblock>
而不是:
<codeblock>1
2
3</codeblock>
我怎样才能摆脱这些,我已经尝试删除 current-group() 中的 spaces 但没有成功。
建议的编辑给我:
<codeblock>
1
2
3
</codeblock>
但是怪白的问题依旧space。 current-group() 包含 " ", <codeblock>, " ", <codeblock>, " ", <codeblock>, " "
,空格 space 中有回车 return。
我觉得
<?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" exclude-result-prefixes="xs" version="2.0">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[codeblock | msgblock]">
<xsl:copy>
<xsl:for-each-group select="node()"
group-adjacent="boolean(self::text()[not(normalize-space())] | self::codeblock | self::msgblock)">
<xsl:choose>
<xsl:when test="current-grouping-key() and current-group()[self::*]">
<xsl:element name="{name(current-group()[self::*[1]][1])}">
<xsl:apply-templates select="current-group()"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="codeblock | msgblock">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
分组并保留文本,您可能需要调整输出分组内容的部分,因为我不确定您想要哪个确切结果。
关于白色 space 的问题,假设您在 codeblock
和 msgblock
元素中只有纯文本,那么您可以简化
<xsl:choose>
<xsl:when test="current-grouping-key() and current-group()[self::*]">
<xsl:element name="{name(current-group()[self::*[1]][1])}">
<xsl:apply-templates select="current-group()"/>
</xsl:element>
</xsl:when>
到
<xsl:choose>
<xsl:when test="current-grouping-key() and current-group()[self::*]">
<xsl:element name="{name(current-group()[self::*[1]][1])}">
<xsl:value-of select="current-group()[self::*]" separator=" "/>
</xsl:element>
</xsl:when>
我遇到一个问题,当我尝试将代码行分组到块中时,我的 parent 的文本丢失了,我不知道为什么。
XML
<body>
<ul>
<li>before
<filepath>one test</filepath> now some code:
<codeblock>1</codeblock>
<codeblock>2</codeblock>
after text</li>
</ul>
<section>
<title>Test2</title>
<p>qqqq</p>
<codeblock>1</codeblock>
<codeblock>2</codeblock>
<codeblock>3</codeblock>
</section>
</body>
XSLT
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:template match="@*|node()">
<xsl:choose>
<xsl:when test="./codeblock[1] or ./msgblock[1]">
<xsl:call-template name="merge-codeblock">
<xsl:with-param name="container" select="."/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="merge-codeblock">
<xsl:param name="container"/>
<xsl:copy>
<xsl:for-each-group select="*" group-adjacent="boolean(self::codeblock or self::msgblock)">
<xsl:choose>
<xsl:when test="current-grouping-key() and count(current-group()) gt 1">
<xsl:element name="{name()}">
<xsl:variable name="name" select="current-group()/node()" />
<xsl:for-each select="current-group()/node()">
<xsl:variable name="namee" select="current()" />
<xsl:apply-templates select="current()" />
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当前结果
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE task PUBLIC "-//OASIS//DTD DITA Task//EN" "dtd/task.dtd"><!--<!DOCTYPE task PUBLIC "-//OASIS//DTD DITA Task//EN" "dtd/task.dtd">--><body>
<ul>
<li><!-- not ok! I lost my li/text() -->
<filepath>one test</filepath>
<codeblock>1
2
</codeblock>
</li>
</ul>
<section>
<title>Test</title>
<p>fddsfsd</p>
<codeblock>fdsfds</codeblock>
</section>
<section>
<title>Test2</title>
<p>qqqq</p>
<codeblock>1
2
3
</codeblock>
</section>
</body>
我已经尝试将 |text()
添加到我的组选择器中,这解决了问题,但是我的 codeblock
元素不再合并。
我做错了什么?
编辑: Martin 的回答解决了 LI 问题,但不幸的是,我现在在代码块行之前有额外的 spaces,在第一个代码块之后有一个回车 return:
<codeblock>
1
2
3
</codeblock>
而不是:
<codeblock>1
2
3</codeblock>
我怎样才能摆脱这些,我已经尝试删除 current-group() 中的 spaces 但没有成功。
建议的编辑给我:
<codeblock>
1
2
3
</codeblock>
但是怪白的问题依旧space。 current-group() 包含 " ", <codeblock>, " ", <codeblock>, " ", <codeblock>, " "
,空格 space 中有回车 return。
我觉得
<?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" exclude-result-prefixes="xs" version="2.0">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[codeblock | msgblock]">
<xsl:copy>
<xsl:for-each-group select="node()"
group-adjacent="boolean(self::text()[not(normalize-space())] | self::codeblock | self::msgblock)">
<xsl:choose>
<xsl:when test="current-grouping-key() and current-group()[self::*]">
<xsl:element name="{name(current-group()[self::*[1]][1])}">
<xsl:apply-templates select="current-group()"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="codeblock | msgblock">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
分组并保留文本,您可能需要调整输出分组内容的部分,因为我不确定您想要哪个确切结果。
关于白色 space 的问题,假设您在 codeblock
和 msgblock
元素中只有纯文本,那么您可以简化
<xsl:choose>
<xsl:when test="current-grouping-key() and current-group()[self::*]">
<xsl:element name="{name(current-group()[self::*[1]][1])}">
<xsl:apply-templates select="current-group()"/>
</xsl:element>
</xsl:when>
到
<xsl:choose>
<xsl:when test="current-grouping-key() and current-group()[self::*]">
<xsl:element name="{name(current-group()[self::*[1]][1])}">
<xsl:value-of select="current-group()[self::*]" separator=" "/>
</xsl:element>
</xsl:when>