我是一名尝试进行以下转换的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>
...
我想用它的父级名称替换每个元素“item”,然后删除它们自己的父级。
这是我到目前为止所得到的:
<?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>
我是朝着正确的方向前进的吗?
答案 0 :(得分:3)
方向是正确的,从父级检索元素名称是个好主意,但是
<xsl:apply-templates select=".."/>
接下来将处理父元素的节点。但是,您应该继续处理item
元素的内容。
如果删除parent
元素,那么结果显然是格式错误的XML。所以我假设以下XML输入(所有内容都包含root
元素):
XML输入
<root>
<parent>
<item>
<val1>...</val1>
<val2>...</val2>
</item>
<item>
<val2>...</val2>
</item>
</parent>
</root>
<强>样式表强>
<?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="parent">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="item">
<xsl:element name="{parent::*/name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:transform>
XML输出
<root>
<parent>
<val1>...</val1>
<val2>...</val2>
</parent>
<parent>
<val2>...</val2>
</parent>
</root>
如果规则仅依赖于元素的层次结构,请尝试以下样式表。它没有提到任何具体的元素名称。
<?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输出
<root>
<parent>
<val1>...</val1>
<val2>...</val2>
</parent>
<parent>
<val2>...</val2>
</parent>
</root>
编辑
使用@ 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输出
<student>
<contact>
<phone>000000001</phone>
</contact>
<contact>
<phone>000000002</phone>
</contact>
<name>John</name>
</student>
<student>
<name>Francis</name>
</student>
答案 1 :(得分:2)
这是Matthias
的优秀答案的延伸从您对其他答案的评论看起来像:
item
,但“parent”元素可以被称为任何内容另一个答案提供了您需要的基本逻辑 - 一个处理大多数事情的身份模板,一个匹配刚刚执行apply-templates
的父模板的模板和一个匹配带有元素名称的item
的模板来自父母 - 但如果我们不知道它的名字,我们如何匹配父母?那么,这个怎么样:
<xsl:template match="*[*][not(*[not(self::item)])]">
<xsl:apply-templates />
</xsl:template>
这将匹配其子项 all 名为item
的任何元素(双重否定表示“没有名称不是项目的子元素”,但这将包括案例一个没有子元素的元素,所以初始[*]
是确保至少有一个子元素所必需的。)