如何将子节点转换为当前节点的属性

时间:2011-02-22 18:25:42

标签: xml xslt

我在这里找到了类似的问题:

  

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>

提前致谢。

4 个答案:

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