我在这里找到了类似的问题:
How to read attribute of a parent node from a child node in XSLT
但不完全是我需要的东西。假设在这里使用相同的例子:
<A>
<b attr1="xx">
<c>
Turn this into an Attribute
</c>
</b>
</A>
我希望在xslt之后生成的xml如下:
<A>
<b attr1="xx" cAttr="Turn this into an Attribute">
</b>
</A>
使用我目前的知识,我只能设法摆脱节点或将其名称更改为所需的名称“cAttr”,但我真的不知道如何将整个节点转换为父节点的属性,只知道如何引用父节点的属性字段对我来说没什么帮助。
我目前的代码看起来像这样:
<xsl:template match="c">
<xsl:element name="cAttr">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
提前致谢。
答案 0 :(得分:2)
<!-- match b node -->
<xsl:template match="b">
<!-- apply templates on all attributes and nodes. see two templates below -->
<xsl:apply-templates select="@*|node()"/>
</xsl:template>
<!-- copy all existing attrs -->
<xsl:template match="b/@*">
<xsl:copy-of select="."/>
</xsl:template>
<!-- populate attributes from nodes -->
<xsl:template match="b/node()">
<xsl:attribute name="{name()}Attr"> <!-- attribute name -->
<xsl:value-of select="text()"/> <!-- attribute value -->
</xsl:attribute>
<!-- match all attributes on child node -->
<xsl:apply-templates select="@*">
<xsl:with-param name="prefix" select="name()"/> <!-- pass node name to template -->
</xsl:apply-templates>
</xsl:template>
<xsl:template match="b/node()/@*">
<xsl:param name="prefix"/>
<!-- creates attribute prefixed with child node name -->
<xsl:attribute name="{$prefix}-{name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
答案 1 :(得分:1)
除了@Flack正确的推送风格,只是为了好玩,两种拉式方式:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="b/*[1][self::c]" name="attribute" priority="1">
<xsl:attribute name="cAttr">
<xsl:value-of select="../c"/>
</xsl:attribute>
</xsl:template>
<xsl:template match="b[c]/*[1]">
<xsl:call-template name="attribute"/>
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template match="b/c"/>
</xsl:stylesheet>
注意:只有模式匹配的规则才会覆盖身份规则。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="b[c]/*[1]" priority="1">
<xsl:attribute name="cAttr">
<xsl:value-of select="../c"/>
</xsl:attribute>
<xsl:if test="not(self::c)">
<xsl:call-template name="identity"/>
</xsl:if>
</xsl:template>
<xsl:template match="b/c"/>
</xsl:stylesheet>
注意:一条规则,但有一些xsl:if
。
两个输出:
<A>
<b attr1="xx" cAttr="Turn this into an Attribute"></b>
</A>
修改:哎呀!我错过了剥离规则。
答案 2 :(得分:0)
不如Gleb的版本好,但如果我已经浪费了我的时间,为什么不发布它?)
<!-- Identity template -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- assemble b element -->
<xsl:template match="b">
<b>
<xsl:attribute name="attr1">
<xsl:value-of select="@attr1" />
</xsl:attribute>
<xsl:attribute name="cAttr">
<xsl:value-of select="c" />
</xsl:attribute>
</b>
</xsl:template>
<!-- ignore c element -->
<xsl:template match="c" />
答案 3 :(得分:0)
我更喜欢更简洁(虽然不太通用)设计:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="b">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:attribute name="cAttr">
<xsl:value-of select="normalize-space(c)"/>
</xsl:attribute>
<xsl:apply-templates select="*[not(self::c)]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
像这样应用于XML:
<A>
<b attr1="xx">
<d>SomeNode</d>
<c>
Turn this into an Attribute
</c>
<f>SomeMoreNode</f>
</b>
</A>
结果将是:
<A>
<b attr1="xx" cAttr="Turn this into an Attribute">
<d>SomeNode</d>
<f>SomeMoreNode</f>
</b>
</A>