2015-01-02 2 views
0

Мне нужно сгладить XML с помощью XSLT. Ниже приводится XMLXSLT для выравнивания XML (имеет повторяющиеся элементы)

<Parent> 
    <Child type="X"> 
     <data value="1" /> 
     <data value="2" /> 
     <data value="3" /> 
    </Child> 
    <Child type="Y"> 
     <data value="5" /> 
     <data value="6" /> 
     <data value="7" /> 
     <data value="8" /> 
    </Child> 
</Parent> 

Желаемая выход

<Parent> 
    <Child type="X" data1_value="1" data2_value="2" data3_value="3"/> 
    <Child type="Y" data1_value="5" data2_value="6" data3_value="7" data4_value="8"/> 
</Parent> 
+0

Будет ли вход всегда иметь только 3 уровня глубины? – JLRishe

+0

Не совсем 3 уровня, но я хотел получить представление о том, как этого достичь. Благодаря! – mantlex

+0

Вы уверены, что хотите сделать это? Вы принимаете совершенно хорошую структуру XML и превращаете ее в ужасную. - P.S. Это не называется «сплющиванием». Плоский результат будет реплицировать атрибут 'type' на каждый узел' data' и исключить «дочерние» узлы. –

ответ

1

Вы не приложили много усилий в определении деталей вашего сценария, но это должно работать для этого входа:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" 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:variable name="name" select="local-name()" /> 
    <xsl:variable name="num"> 
     <xsl:number count="*[local-name() = $name]"/> 
    </xsl:variable> 

    <xsl:apply-templates select="@*"> 
     <xsl:with-param name="prefix" select="concat(local-name(), $num)" /> 
    </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="/*/*/*/@*"> 
    <xsl:param name="prefix" /> 

    <xsl:attribute name="{concat($prefix, '_', local-name())}"> 
     <xsl:value-of select="." /> 
    </xsl:attribute> 
    </xsl:template> 

</xsl:stylesheet> 

При запуске на входе в образец результат:

<Parent> 
    <Child type="X" data1_value="1" data2_value="2" data3_value="3" /> 
    <Child type="Y" data1_value="5" data2_value="6" data3_value="7" data4_value="8" /> 
</Parent> 

Если есть Grandchild элементов с разными названиями, например:

<Parent> 
    <Child type="X"> 
     <data value="1" /> 
     <data value="2" /> 
     <data value="3" /> 
    </Child> 
    <Child type="Y"> 
     <data value="5" /> 
     <mydata value="6" /> 
     <data value="7" /> 
     <mydata value="8" /> 
    </Child> 
</Parent> 

Тогда каждое отдельное имя будет нумеруется отдельно (я предполагаю, что это предпочтительнее нумерации все вместе):

<Parent> 
    <Child type="X" data1_value="1" data2_value="2" data3_value="3" /> 
    <Child type="Y" data1_value="5" mydata1_value="6" data2_value="7" mydata2_value="8" /> 
</Parent> 
+0

Спасибо, я постараюсь применить это к моему сценарию. – mantlex

0
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" encoding="utf-8" indent="yes" /> 
    <xsl:template match="/"> 
     <Parent> 
     <xsl:for-each select="/Parent/Child"> 
      <Child type="{@type}"> 
       <xsl:for-each select="data"> 
        <xsl:attribute name="data{position()}_value"> 
        <xsl:value-of select="@value" /> 
        </xsl:attribute> 
       </xsl:for-each> 
      </Child> 
     </xsl:for-each> 
     </Parent> 
    </xsl:template> 
</xsl:stylesheet> 
Смежные вопросы