Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml XSLT将元素替换为其父元素的名称_Xml_Xslt - Fatal编程技术网

Xml XSLT将元素替换为其父元素的名称

Xml XSLT将元素替换为其父元素的名称,xml,xslt,Xml,Xslt,我是一名XSLT开发人员,正在尝试进行以下转换: 资料来源: ... <student> <item> <contact> <item> <phone>000000001</phone> </item> <item> <phone>

我是一名XSLT开发人员,正在尝试进行以下转换:

资料来源:

...
<student>
    <item>
        <contact>
            <item>
                <phone>000000001</phone>
            </item>
            <item>
                <phone>000000002</phone>
            </item>
        </contact>
        <name>John</name>
    </item>
    <item>
        <name>Francis</name>
    </item>
</student>

...
结果:

...
    <student>
        <contact>
            <phone></phone>
        </contact>
        <contact>
            <phone></phone>
        </contact>
        <name>John</name>
    </student>
    <student>
        <name>Francis</name>
    </student>

...
我想用父元素的名称替换每个元素项,然后删除它们自己的父元素

到目前为止,我得到的是:

<?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
</xsl:template>


<xsl:template match="/*">
        <xsl:apply-templates/>
</xsl:template>

<xsl:template match="item">
    <xsl:element name="{parent::*/name()}">
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

方向正确吗?

方向是正确的,从父元素检索元素名是个好主意,但是

<xsl:apply-templates select=".."/>
样式表

XML输出

如果规则仅依赖于元素的层次结构,请尝试以下样式表。它没有提到任何具体的元素名称

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes" />

    <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/*/*">
            <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="/*/*/*">
        <xsl:element name="{parent::*/name()}">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

</xsl:transform>
XML输出

编辑

使用@Ian的建议:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes" />

    <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*[*][not(*[not(self::item)])]">
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="item">
        <xsl:element name="{parent::*/name()}">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

</xsl:transform>
XML输出


方向是正确的,从父元素检索元素名是一个好主意,但是

<xsl:apply-templates select=".."/>
样式表

XML输出

如果规则仅依赖于元素的层次结构,请尝试以下样式表。它没有提到任何具体的元素名称

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes" />

    <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/*/*">
            <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="/*/*/*">
        <xsl:element name="{parent::*/name()}">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

</xsl:transform>
XML输出

编辑

使用@Ian的建议:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes" />

    <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*[*][not(*[not(self::item)])]">
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="item">
        <xsl:element name="{parent::*/name()}">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

</xsl:transform>
XML输出

这是Matthias优秀答案的延伸

从你对另一个答案的评论来看:

此父级/项结构可以位于较大文档中的任何位置 item元素始终被称为item,但父元素可以被称为任何东西 另一个答案给出了您需要的基本逻辑-一个处理大多数事情的标识模板,一个匹配只应用模板的父级的模板,以及一个匹配从父级获取元素名称的项的模板-但是如果我们不知道父级的名称,我们如何匹配父级?那么,这个怎么样:

<xsl:template match="*[*][not(*[not(self::item)])]">
    <xsl:apply-templates />
</xsl:template>
这将匹配所有子元素都命名为item的任何元素。双负表示没有名称不是item的子元素,但这将包括一个没有子元素的元素的情况,因此初始[*]必须确保至少有一个子元素。

这是Matthias优秀答案的扩展

从你对另一个答案的评论来看:

此父级/项结构可以位于较大文档中的任何位置 item元素始终被称为item,但父元素可以被称为任何东西 另一个答案给出了您需要的基本逻辑-一个处理大多数事情的标识模板,一个匹配只应用模板的父级的模板,以及一个匹配从父级获取元素名称的项的模板-但是如果我们不知道父级的名称,我们如何匹配父级?那么,这个怎么样:

<xsl:template match="*[*][not(*[not(self::item)])]">
    <xsl:apply-templates />
</xsl:template>


这将匹配所有子元素都命名为item的元素。双负数表示没有名称不是item的子元素,但这将包括没有子元素的元素的情况,因此必须使用首字母[*],以确保至少有一个子元素。

问题需要更多信息。根节点呢?是否也要对根节点执行相同的操作?如果这样做,最终会生成无效的XML..我更新了原始帖子。根元素旁边永远不会有item元素。该问题需要更多信息。根节点呢?是否也要对根节点执行相同的操作?如果这样做,最终会生成无效的XML..我更新了原始帖子。根元素旁边永远不会有item元素。谢谢您的回复。问题是我不知道该项的父项名称,这意味着我无法匹配它。@sovesky然后请查看第二个样式表-我已经编辑了我的答案。谢谢。我快到了。我更新了原来的帖子。代码可以工作,但不适用于嵌套项结构。@sovesky再次编辑了我的答案,合并了Ian建议的模板。@sovesky如果最终证明您确实需要XSLT 1.0而不是2.0,那么您需要在样式表中更改的唯一一件事就是用name替换parent:::*/name。谢谢您的回复。问题是我不知道该项的父项名称,这意味着我无法匹配它。@sovesky然后请查看第二个样式表-我已经编辑了我的答案。谢谢。我快到了。我更新了原来的帖子。代码可以工作,但不适用于嵌套项结构。@sovesky再次编辑了我的答案,合并了Ian建议的模板。@sovesky如果最终证明您确实需要XSLT 1.0而不是2.0,那么您需要在样式表中更改的唯一一件事就是用name替换parent:::*/name。我仍然认为xpath中有一个很大的遗漏,无法指定一个元素,其中所有子元素都匹配一个模式,而不是任何子元素。不幸的是,双负数是必需的,如果括号错误,通常很难调试。@Flynn1179给出的问题是XSLT 2.0没有明确提到,但您可以从../name中看出,您可以将其写为[every$n in*满足$n/name eq‘item’]啊。。不幸的是,我太习惯XSLT1了。几乎无法使用MSXSL或浏览
我在做变换。但情况未必如此——有可能OP没有意识到这在XSLT1中不起作用,毕竟这不起作用。@flyn1179确实如此。当你第一次看到这个双重否定的习语时,它看起来有点奇怪,但它只是一个习语,一旦你习惯了它,你就可以识别它的意思,而不必每次都对它进行解码。+1这是一个有用的扩展,可以将逻辑应用到层次结构中的任何地方。我仍然认为这是xpath中的一个重大遗漏,无法指定一个元素,其中所有子元素都匹配一个模式,而不是任何子元素。不幸的是,双负数是必需的,如果括号错误,通常很难调试。@Flynn1179给出的问题是XSLT 2.0没有明确提到,但您可以从../name中看出,您可以将其写为[every$n in*满足$n/name eq‘item’]啊。。不幸的是,我太习惯XSLT1了。在我所在的地方,我一直在使用MSXSL或浏览器进行转换。但情况未必如此——有可能OP没有意识到这在XSLT1中不起作用,毕竟这不起作用。@flyn1179确实如此。当你第一次看到这个双重否定的习语时,它看起来有点奇怪,但它只是一个习语,一旦你习惯了它,你就可以识别它的意思,而不必每次都对它进行解码。
<xsl:template match="*[*][not(*[not(self::item)])]">
    <xsl:apply-templates />
</xsl:template>