XSL добавление атрибута к родителю на основе дочернего - PullRequest
2 голосов
/ 29 февраля 2012

Я начал проект в php, используя XML, и теперь мне нужно применить преобразование, поэтому я впервые обнаружил XSL ...

Я столкнулся с проблемой: как создать XSLсделать следующее преобразование: - узел, который начинается с "attrib-" для преобразования в атрибут родительского узла

Пример:

<a1>
  <b1>
    <attrib-c1>12</attrib-c1>
    <c2>23</c2>
  </b1>
</a1>

должен стать:

<a1>
  <b1 c1="12">
    <c2>23</c2>
  </b1>
</a1>

Я начал решение, как это:

<xsl:stylesheet>
  <xsl:output method="xml"/>
  <xsl:template match="@*|*|text()">
    <xsl:copy>
      <xsl:apply-templates select="@*|*|text()"/>
    </xsl:copy>
  </xsl:template>
...
</xsl:stylesheet>

Мне понадобится помощь для решения этой задачи.Заранее спасибо ...

Ответы [ 3 ]

3 голосов
/ 29 февраля 2012

Ввод XML (изменен для небольшого увеличения сложности.)

<a1>
  <b1 existing="attr">
    <attrib-c1>12</attrib-c1>
    <c2>23</c2>
    <attrib-dh>DevNull</attrib-dh>
  </b1>
</a1>

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="*">
    <xsl:copy>
      <xsl:apply-templates select="*[starts-with(name(),'attrib')]" mode="attr"/>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*[starts-with(name(),'attrib')]"/>

  <xsl:template match="*" mode="attr">
    <xsl:attribute name="{substring-after(name(),'-')}">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>  

</xsl:stylesheet>

Вывод XML

<a1>
   <b1 c1="12" dh="DevNull" existing="attr">
      <c2>23</c2>
   </b1>
</a1>
1 голос
/ 29 февраля 2012

Это почти то же решение, что и у DevNull, но в случае конфликта между существующим атрибутом и новым, определенным дочерним элементом, последний заменяет первый :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output 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:copy>
   <xsl:apply-templates select="@*"/>
   <xsl:apply-templates mode="attr" select="*[starts-with(name(), 'attrib-')]"/>
   <xsl:apply-templates/>
  </xsl:copy>
 </xsl:template>

 <xsl:template mode="attr" match="*[starts-with(name(), 'attrib-')]">
  <xsl:attribute name="{substring-after(name(), 'attrib-')}">
    <xsl:value-of select="."/>
  </xsl:attribute>
 </xsl:template>

 <xsl:template match="*[starts-with(name(), 'attrib-')]"/>
</xsl:stylesheet>

когда это преобразование применяется к следующему документу XML :

<a1>
  <b1 existing="attr" x="Y">
    <attrib-new>12</attrib-new>
    <c2>23</c2>
    <attrib-new2>ABCD</attrib-new2>
    <attrib-x>Z</attrib-x>
  </b1>
</a1>

желаемый, правильный результат получается :

<a1>
   <b1 existing="attr" x="Z" new="12" new2="ABCD">
      <c2>23</c2>
   </b1>
</a1>
1 голос
/ 29 февраля 2012
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0">

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

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

    <!-- match elements with children like attrib- and copy/pass -->
    <xsl:template match="*[*[starts-with(name(.),'attrib')]]">
        <xsl:copy>
         <xsl:apply-templates select="*[starts-with(name(.),'attrib')]"/>
         <xsl:apply-templates select="@*|*[not(starts-with(name(.),'attrib'))]"/>
        </xsl:copy>
    </xsl:template>

    <!-- match elements like attrib- and output them as attribute -->
    <xsl:template match="*[starts-with(name(.),'attrib')]">
        <xsl:attribute name="{substring-after(name(.),'attrib-')}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...