Как превратить дочерний узел в атрибут текущего узла - PullRequest
0 голосов
/ 22 февраля 2011

Я нашел похожий вопрос здесь:

Как прочитать атрибут родительского узла из дочернего узла в XSLT

Но неименно то, что мне нужно здесь.Предположим, используя тот же пример здесь:

<A>
 <b attr1="xx">
   <c>
    Turn this into an Attribute  
   </c>
 </b>
</A>

, и я хочу, чтобы полученный xml после xslt выглядел следующим образом:

 <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 ]

2 голосов
/ 22 февраля 2011
<!-- 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 голос
/ 23 февраля 2011

Помимо @Flack корректного стиля push и просто для удовольствия, два подхода стиля pull:

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

Редактировать : Упс!Я пропустил правило зачистки.

0 голосов
/ 23 февраля 2011

Я предпочитаю более лаконичный (хотя и менее общий) дизайн:

<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>
0 голосов
/ 22 февраля 2011

Не так хорошо, как версия Глеба, но почему бы не опубликовать ее, если я уже потратил впустую свое время =;)

<!-- 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" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...