1

XMLファイルをCSVファイルに変換する必要があります。入力XMLファイルは次のようなものです。

<Person>
    <Name>John</Name>
    <FamilyMembers>
        <FamilyMember>
            <Name>Lisa</Name>
            <Type>Sister</Type>
        </FamilyMember>
        <FamilyMember>
            <Name>Tom</Name>
            <Type>Brother</Type>
        </FamilyMember>
    </FamilyMembers>
</Person>
<Person>
    <Name>Daniel</Name>
    <FamilyMembers>
        <FamilyMember>
            <Name>Peter</Name>
            <Type>Father</Type>
        </FamilyMember>
    </FamilyMembers>
</Person>

最終的なCSVファイルは次のようになります。

Name;Sister;Brother;Father
John;Lisa;Tom
Daniel;;;Peter

基本的に必要なのは、コンテンツが異なる「タイプ」ノードごとに1つの列です。「タイプ」の制限はありません。

編集:私の実際のXSLTはそれを次のようなCSVに解析します:

Name;Name;Type
John;Lisa;Sister
John;Tom;Brother
Daniel;Peter;Father 

私の問題を解決する方法を誰かが知っていますか?

アンドレ

4

3 に答える 3

2

これは通常、問題を解決する最も効率的な方法であるxsl:keyを利用する XSLT1.0 ソリューションです (Martin に感謝します!) 。基本的にTypeでグループ化しようとしているので、異なるファミリーメンバーのタイプを取得するには、次のようにキーを定義できます

<xsl:key name="Type" match="Type" use="." />

次に、ヘッダー行について、実際に個別のタイプを取得するために、すべてのタイプを反復しますが、指定された値のキーで最初に出現するレコードのみを選択します

<xsl:apply-templates 
   select="//Type[generate-id() = generate-id(key('Type', .)[1])]" 
   mode="header" />

(ヘッダーのモードは、Type レコードがすぐに家族の別の場所で照合されるため、一致するテンプレートを区別する必要があるためです)

次に、各Personレコードを選択し、そのようなレコードごとに個別のタイプを再度選択しますが、今回は現在のPersonレコードをパラメーターとして渡して、関連する家族を抽出できるようにします。

<xsl:apply-templates 
   select="//Type[generate-id() = generate-id(key('Type', .)[1])]" 
   mode="family">
   <xsl:with-param name="Person" select="." />
 </xsl:apply-templates>

そして、これに一致するテンプレート(ファミリーのモードを使用)で、タイプの関連するファミリーメンバーを出力できます

ここに完全な XSLT があります

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>
   <xsl:key name="Type" match="Type" use="." />

   <xsl:template match="/*">
      <xsl:text>Name</xsl:text>
      <xsl:apply-templates select="//Type[generate-id() = generate-id(key('Type', .)[1])]" mode="header" />
      <xsl:text>&#10;</xsl:text>
      <xsl:apply-templates select="Person" />
   </xsl:template>

   <xsl:template match="Person">
      <xsl:value-of select="Name" />
      <xsl:apply-templates select="//Type[generate-id() = generate-id(key('Type', .)[1])]" mode="family">
         <xsl:with-param name="Person" select="." />
      </xsl:apply-templates>
      <xsl:text>&#10;</xsl:text>
   </xsl:template>

   <xsl:template match="Type" mode="header">
      <xsl:text>;</xsl:text>
      <xsl:value-of select="." />
   </xsl:template>

   <xsl:template match="Type" mode="family">
      <xsl:param name="Person" />
      <xsl:text>;</xsl:text>
      <xsl:value-of select="$Person/FamilyMembers/FamilyMember[Type=current()]/Name" />
   </xsl:template>
</xsl:stylesheet>

XML に適用すると (単一のルート要素を想定)、以下が出力されます。

Name;Sister;Brother;Father
John;Lisa;Tom;
Daniel;;;Peter

これは、Person ごとに複数の兄弟や姉妹などを持つことができないことを前提としています。

于 2012-11-08T12:22:48.937 に答える
0

スタイルシート

<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="text"/>

<xsl:template match="/">
    <xsl:text>Name;Sister;Brother;Father&#xd;</xsl:text>
    <xsl:for-each select="Persons/Person">
        <xsl:variable name="name" select="Name"/>
        <xsl:variable name="others">
            <xsl:value-of select="FamilyMembers/FamilyMember[Type/text()='Sister']/Name/text()"/>
            <xsl:text>;</xsl:text>
            <xsl:value-of select="FamilyMembers/FamilyMember[Type/text()='Brother']/Name/text()"/>
            <xsl:text>;</xsl:text>
            <xsl:value-of select="FamilyMembers/FamilyMember[Type/text()='Father']/Name/text()"/>
            <xsl:text>&#xd;</xsl:text>          
        </xsl:variable>
        <xsl:value-of select="concat($name,';',$others)"/>
    </xsl:for-each> 
</xsl:template>

</xsl:stylesheet>

XMLに適用した場合(整形式になるように変更):

<Persons>
    <Person>
        <Name>John</Name>
        <FamilyMembers>
            <FamilyMember>
                <Name>Lisa</Name>
                <Type>Sister</Type>
            </FamilyMember>
            <FamilyMember>
                <Name>Tom</Name>
                <Type>Brother</Type>
            </FamilyMember>
        </FamilyMembers>
    </Person>
    <Person>
        <Name>Daniel</Name>
        <FamilyMembers>
            <FamilyMember>
                <Name>Peter</Name>
                <Type>Father</Type>
            </FamilyMember>
        </FamilyMembers>
    </Person>
</Persons>

結果

Name;Sister;Brother;Father
John;Lisa;Tom;
Daniel;;;Peter

お役に立てれば。

于 2012-11-08T12:02:12.557 に答える
0

XSLT 2.0 を使ってみました:

<xsl:stylesheet 
  version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs">

<xsl:param name="sep" as="xs:string" select="';'"/>

<xsl:key name="k1" match="FamilyMember" use="Type"/>

<xsl:output method="text"/>

<xsl:variable name="cols" as="xs:string*" select="('Name', distinct-values(//Person/FamilyMembers/FamilyMember/Type))"/>

<xsl:template match="/">
  <xsl:value-of select="$cols" separator="{$sep}"/>
  <xsl:text>&#10;</xsl:text>
  <xsl:apply-templates select="//Person"/>
</xsl:template>

<xsl:template match="Person">
  <xsl:value-of select="Name"/>
  <xsl:variable name="cells" as="xs:string*" select="
    for $col in $cols[position() gt 1] return (key('k1', $col, current())/Name, '')[1]"/>
  <xsl:sequence select="if (not(empty($cells))) then concat($sep, string-join($cells, $sep)) else ()"/>  
  <xsl:text>&#10;</xsl:text>
</xsl:template>

</xsl:stylesheet>

変換

<Persons>
<Person>
    <Name>John</Name>
    <FamilyMembers>
        <FamilyMember>
            <Name>Lisa</Name>
            <Type>Sister</Type>
        </FamilyMember>
        <FamilyMember>
            <Name>Tom</Name>
            <Type>Brother</Type>
        </FamilyMember>
    </FamilyMembers>
</Person>
<Person>
    <Name>Daniel</Name>
    <FamilyMembers>
        <FamilyMember>
            <Name>Peter</Name>
            <Type>Father</Type>
        </FamilyMember>
    </FamilyMembers>
</Person>
</Persons>

の中へ

Name;Sister;Brother;Father
John;Lisa;Tom;
Daniel;;;Peter

後でそれを XSLT 1.0 ソリューションに変換しようとするかもしれませんが、Tim C がすでに XSLT 1.0 で解決しようとしている場合、彼はより速くなると思います。

于 2012-11-08T12:04:21.783 に答える