我怎么能得到一个孩子,一个孩子生产的东西,我不需要在他的父母身上?

时间:2016-09-23 13:39:39

标签: xml xslt xslt-2.0

代码是最好的语言

来源[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我无法显示任何样式表,因为这是完全理论化的东西。请让我通过评论了解我的帖子并描述问题。非常感谢您的努力,至少花时间阅读。

1 个答案:

答案 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>