2014-11-18 4 views
0

У меня есть файл XML:XSLT 2.0 создать документ для каждого элемента

<xml> 
    <metadata> 
     <book></book> 
     <info></info> 
     <name></name> 
    </metadata> 
    <customer> 
     <person name = "p1" book="x"></person> 
     <person name = "p2" book="y"></person> 
    </customer> 
</xml> 

Что мне нужно, чтобы создать выходной файл для каждого клиента, какой containts метаданных:

output1:

<xml> 
    <metadata> 
     <book></book> 
     <info></info> 
     <name></name> 
    </metadata> 
    <customer> 
     <person name = "p1" book="x"></person> 
    </customer> 
    </xml> 

output2:

<xml> 
    <metadata> 
     <book></book> 
     <info></info> 
     <name></name> 
    </metadata> 
    <customer> 
     <person name = "p2" book="y"></person> 
    </customer> 
</xml> 

то, что я до сих пор:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" name="xml" /> 
    <xsl:strip-space elements="*" /> 
<xsl:variable name="persons" select="/xml/customer/person" /> 

<xsl:template match="xml"> 
     <xsl:for-each select="$persons"> 
      <xsl:variable name="filename" select="concat('\output\',@name,'.xml')" /> 
      <xsl:result-document href="{$filename}" format="xml"> 
       <xsl:copy> 
        <xsl:apply-templates/> 
       </xsl:copy> 
      </xsl:result-document> 
     </xsl:for-each> 
    </xsl:template>  


<xsl:template match="metadata"> 
    <xsl:copy-of select="@*" /> 
</xsl:template> 

<xsl:template match="customer"> 
    <xsl:copy-of select="@*" /> 
</xsl:template> 

</xsl:stylesheet> 

но что код я могу создать файл для каждого человека, но метаданные не в файле. Поэтому в моем цикле foreach я должен применять шаблоны для всех узлов. Есть ли способ «перейти» к корневому узлу?

ответ

2

Во-первых, когда вы применяете ваш xsl:for-each вы находитесь в области видимости person элемента, если вы хотите скопировать metada, вы не можете применить шаблоны на «*» (который является то, что вы сделали с неявным <xsl:apply-templates/> и означает «все дочерние элементы»).

Во-вторых, ваши шаблоны, соответствующие customer и metadata, копируют только узлы атрибутов, а не сам узел, а затем не могут работать. На самом деле ни один из них никогда не был сопоставлен, потому что вы применяли шаблоны из контекста персонажа, то есть на человека-ребенка (и у вас его нет) ...

Итак, я думаю, что это то, чего вы пытаетесь достичь (сделано полностью для каждого , но вместо этого можно использовать «матч-дизайн»):

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" name="xml" /> 
    <xsl:strip-space elements="*" /> 
    <xsl:template match="xml"> 
      <xsl:for-each select="customer/person"> 
       <xsl:variable name="filename" select="concat('\output\',@name,'.xml')" /> 
       <xsl:result-document href="{$filename}" format="xml"> 
        <xml> 
         <xsl:copy-of select="ancestor::xml/metadata"/> 
         <customer> 
          <xsl:copy-of select="."/> 
         </customer> 
        </xml> 
       </xsl:result-document> 
      </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 
+0

+1 для приятного кода. –

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