来源[source.xml]
<asset>
<name>foobar</name>
<paragraph>
I <italic>describe</italic> a function <bold>foobar</bold>.
<headline>I can't be in a paragraph!</headline>
My editor did stuff like this: <bold>Cases: <list><li>item 1</li><li>item 2</li></list></bold>
</paragraph>
</asset>
来源DTD [source.dtd]
<!ELEMENT asset (name,paragraph+)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT paragraph (#PCDATA|bold|headline|italic)*>
<!ELEMENT bold (#PCDATA|list)*>
<!ELEMENT italic (#PCDATA|list)>
<!ELEMENT headline (#PCDATA)>
<!ELEMENT list (li)+>
<!ELEMENT li (#PCDATA)>
预期输出[output.xml]
<asset>
<name>foobar</name>
<p>
I <i>describe</i> a function <b>foobar</b>.
</p><title>I can't be in a paragraph!</title><p>
My editor did stuff like this: <b>Cases: </b>
</p>
<enum><item>item 1</item><item>item 2</item></enum>
</asset>
输出DTD [output.dtd]
<!ELEMENT asset (name,(title|p|enum)*)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT p (#PCDATA|b|i)*>
<!ELEMENT b (#PCDATA)*>
<!ELEMENT i (#PCDATA)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT enum (item)+>
<!ELEMENT item (#PCDATA)>
用语言描述
简化source.xml
output.xml
分别由其负责的dtd文件定义。这些变化很小但对我的问题很重要。
元素headline
[source]映射到title
[output],必须是asset
[output]的子元素。 (上一个/来源:它是paragraph
)的孩子。
元素list
[source]映射到enum
[output],必须是asset
[output]的子元素。 (上一个/来源:它是bold
)的孩子。
XSLT问题开始
我很难构建一个主要基于规则的模板的样式表,因为这个例子只包含大约4%的元素。我期待做什么:
每当我的当前节点中出现“breakelement”时,内容直到“breakelement”被复制,然后“breakelement”被处理(apply-templates,因为可能存在“breakelement”的匹配规则“)之后(如果有内容),当前节点的内容继续。您在p/headline
- &gt;的示例中看到了这一点asset/title
。
每当我将上面相同的逻辑应用于元素bold
时,它将产生以下错误内容。 enum
将在b
之外,但现在它是错误的,因为它必须在p
之外:
内容:
<asset>
<name>foobar</name>
<p>
I <i>describe</i> a function <b>foobar</b>.
</p><title>I can't be in a paragraph!</title><p>
My editor did stuff like this: <b>Cases: </b><enum><item>item 1</item><item>item 2</item></enum>
</p>
</asset>
第二种情况会在我的进程中多次出现,从一个模式到另一个模式,到目前为止我无法处理。
我怎样才能得到满足感,孩子会产生什么,我父母也不需要?
TBH我无法显示任何样式表,因为这是完全理论化的东西。请让我通过评论了解我的帖子并描述问题。非常感谢您的努力,至少花时间阅读。
答案 0 :(得分:0)
我试图用for-each-group group-ending-with="headline | list"
解决这个问题,这是我的尝试:
<?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:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="asset">
<xsl:copy>
<xsl:for-each-group
select="descendant::node()[not(ancestor::headline | ancestor::list)]"
group-ending-with="headline | list">
<xsl:apply-templates select="current-group()/ancestor::*[last() - 1]" mode="strip">
<xsl:with-param name="copy" tunnel="yes"
select="current-group()[position() ne last()]"/>
</xsl:apply-templates>
<xsl:apply-templates select="current-group()[last()]"/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="node()" mode="strip">
<xsl:param name="copy" tunnel="yes"/>
<xsl:if test=". intersect $copy or . intersect $copy/ancestor::*">
<xsl:copy>
<xsl:apply-templates
select="@* | node()[. intersect $copy/ancestor-or-self::node()]" mode="strip">
<xsl:with-param name="copy" tunnel="yes" select="$copy"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:if>
</xsl:template>
<xsl:template match="headline | list" mode="strip"/>
<xsl:template match="headline">
<title>
<xsl:apply-templates/>
</title>
</xsl:template>
<xsl:template match="list">
<enum>
<xsl:apply-templates/>
</enum>
</xsl:template>
<xsl:template match="list/li">
<item>
<xsl:apply-templates/>
</item>
</xsl:template>
</xsl:stylesheet>
它转换
<asset>
<name>foobar</name>
<paragraph>
I <italic>describe</italic> a function <bold>foobar</bold>.
<headline>I can't be in a paragraph!</headline>
My editor did stuff like this: <bold>Cases: <list><li>item 1</li><li>item 2</li></list></bold>
</paragraph>
</asset>
进入
<asset>
<name>foobar</name>
<paragraph>
I <italic>describe</italic> a function <bold>foobar</bold>.
</paragraph>
<title>I can't be in a paragraph!</title>
<paragraph>
My editor did stuff like this: <bold>Cases: </bold>
</paragraph>
<enum>
<item>item 1</item>
<item>item 2</item>
</enum>
</asset>