2013-08-05 9 views
1

Как передать атрибуты дочерним элементам, только если дочерние элементы уже не имеют того же атрибута?XSL передает атрибуты дочерним элементам, если дочерние элементы уже не имеют одного и того же атрибута

XML:

<section> 
    <container attribute1="container1" attribute2="container2"> 
     <p attribute1="test3"/> 
     <ol attribute2="test4"/> 
    <container> 
<section/> 

Вывод должен выглядеть следующим образом:

<section> 
    <p attribute1="test3" attribute2="test2"/> 
    <ol attribute1="container1" attribute2="test4"/> 
</section> 

Это то, что я пробовал:

<xsl:template match="container"> 
    <xsl:apply-templates mode="passAttributeToChild"/> 
</xsl:template> 

<xsl:template match="*" mode="passAttributeToChildren"> 
    <xsl:element name="{name()}"> 
     <xsl:for-each select="@*"> 
      <xsl:choose> 
        <xsl:when test="name() = name(../@*)"/> 
        <xsl:otherwise> 
         <xsl:copy-of select="."/> 
        </xsl:otherwise> 
      </xsl:choose> 
     </xsl:for-each> 
     <xsl:apply-templates select="*|text()"/> 
    </xsl:element> 
</xsl:template> 

Любая помощь будет принята с благодарностью;) Спасибо заранее!

ответ

0

Атрибуты, объявленные более чем один раз, переписывают друг друга, так что это легко.

<xsl:template match="container/*"> 
    <xsl:copy> 
    <xsl:copy-of select="../@*" /> <!-- take default from parent --> 
    <xsl:copy-of select="@*" /> <!-- overwrite if applicable --> 
    <xsl:apply-templates /> 
    </xsl:copy> 
</xsl:template> 

Это предполагает, что вы хотите все родительские атрибуты, так как ваш образец, кажется, указывают. Конечно, вы можете решить, какие атрибуты вы хотите унаследовать:

<xsl:copy-of select="../@attribute1 | ../@attribute2" /> 
    <xsl:copy-of select="@attribute1 | @attribute2"> 
0

Попробуйте это.

<!-- root and static content - container --> 
<xsl:template match="/"> 
    <section> 
     <xsl:apply-templates select='section/container/*' /> 
    </section> 
</xsl:template> 

<!-- iteration content - child nodes --> 
<xsl:template match='*'> 
    <xsl:element name='{name()}'> 
     <xsl:apply-templates select='@*|parent::*/@*' /> 
    </xsl:element> 
</xsl:template> 

<!-- iteration content - attributes --> 
<xsl:template match='@*'> 
    <xsl:attribute name='{name()}'><xsl:value-of select='.' /></xsl:attribute> 
</xsl:template> 

При выводе каждого дочернего узла мы итеративно передаем его атрибуты и атрибуты родителя.

<xsl:apply-templates select='@*|parent::*/@*' /> 

Шаблоны применяются к узлам в порядке их появления в XML. Поэтому родительский (container) узел появляется перед дочерними узлами (конечно), поэтому атрибуты родителя сначала обрабатываются шаблоном атрибутов.

Это удобно, потому что это означает, что шаблон всегда будет показывать предпочтения к собственным атрибутам дочерних узлов, если они уже существуют, потому что они обработаны последними и, таким образом, имеют приоритет над любыми атрибутами с тем же именем от родителя. Таким образом, родитель не может отменить их.

Рабочая демонстрация по адресу this XMLPlayground.

+0

Должно работать, но решение Tomalak было проще применить к моей таблице стилей. В любом случае, спасибо. – user2652424