2012-02-28 3 views
2

Я начал проект в PHP, используя XML, и теперь мне нужно применить преобразование, таким образом, я обнаружил, XSL в первый раз ...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> 

мне нужна помощь, чтобы решить эту задачу. Заранее спасибо ...

+0

Итак, все, что вы сделали, копирует преобразование идентичности. Вы пытались решить проблему? Это домашнее задание? –

ответ

1

Это почти то же решение, что и 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> 
+0

+1 Хорошее обращение с потенциальными конфликтами. –

+0

Отличное решение. Благодаря! –

+0

@ ZoranKalinić: Добро пожаловать. –

3

XML Input (Modified немного увеличить сложность.)

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

<a1> 
    <b1 c1="12" dh="DevNull" existing="attr"> 
     <c2>23</c2> 
    </b1> 
</a1> 
+0

+1 хороший ответ. Кроме того, '' можно заменить на '', правильно? Вы также можете упростить '' to ' LarsH

+0

@LarsH - Спасибо, это отличные предложения. Не уверен, почему я не использовал 'xsl: copy'; это то, что я получаю от спешки. –

+2

+1 за хороший ответ. Кажется, Ларс забыл о действительном повышении. –

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

Рад вас видеть на stackoverflow! +1 для хорошего ответа –

+0

Хорошо, но будьте осторожны с '' , Это не позволяет копировать дочерние элементы, отличные от элементов (например, текстовые узлы, комментарии и т. Д.). – LarsH

+0

Спасибо за ответ! –

Смежные вопросы