2017-11-16 14 views
0

私はXML構造を持っており、これをXSLTで変換したいと思います。ただし、できるだけ動的にすることが重要です。フィードのコピーを作成し、特定のセクションを選択してこれを変換することは可能だと思います。新しいノードが元のXMLに追加されると、この新しいノードをXSLTの出力に含めるために、XSLTに変更を加える必要はありません。元のXMLのXMLノードを1つのコンマ区切りノードにマージする

例:

<?xml version="1.0" encoding="UTF-8"?> 
<catalog week_id="629" generated_at="15.11.2017 23:53" version="2"> 
    <item> 
    <lot> 
     <id>2982641</id> 
     <title_local><![CDATA[Title]]></title_local> 
     <sub_title_local>Subtitle</sub_title_local> 
     <promo>false</promo> 
    </lot> 
    <lot_specifics> 
     <case_material> 
     <name_local>Materiaal kast</name_local> 
     <name_en>Case material</name_en> 
     <slug>s-10-materiaal-kast</slug> 
     <option> 
      <value_local>Verguld</value_local> 
      <value_en>Gold-plated</value_en> 
      <slug_value>1750-verguld</slug_value> 
     </option> 
     <option> 
      <value_local>Zilver</value_local> 
      <value_en>Silver</value_en> 
      <slug_value>1751-silver</slug_value> 
     </option> 
     </case_material> 
    </lot_specifics> 
    <associations> 
     <category_id>1</category_id> 
     <auction_id>2</auction_id> 
    </associations> 
    </item> 
</catalog> 

所望の出力:

<?xml version="1.0" encoding="UTF-8"?> 
<catalog week_id="629" generated_at="15.11.2017 23:53" version="2"> 
    <item> 
    <lot> 
     <id>2982641</id> 
     <title_local><![CDATA[Title]]></title_local> 
     <sub_title_local>Subtitle</sub_title_local> 
     <promo>false</promo> 
    </lot> 
    <lot_specifics> 
     <case_material> 
     <name_local>Materiaal kast</name_local> 
     <name_en>Case material</name_en> 
     <slug>s-10-materiaal-kast</slug> 
     <value_local>Verguld,Silver</value_local> 
     <value_en>Gold-plated,Silver</value_en> 
     </case_material> 
    </lot_specifics> 
    <associations> 
     <category_id>1</category_id> 
     <auction_id>2</auction_id> 
    </associations> 
    </item> 
</catalog> 

私はSO question that pretty much does what I'm aiming forに出くわしたが、私は、このXSLTで完全なXML構造を定義する必要があります。後の段階で他のXMLノードを追加する可能性があり、このXSLTはさまざまな場所で使用されるため、できるだけ低メンテナンスにしたいと考えています。

だと思いますが、率直に言って2番目のxsl:templateの仕組みを理解できません。

すべてのお手伝いが大変ありがとうございます。 XSLTが提供されている場合は、あなたが行っていることについてのコメントを追加することができれば幸いです。

+0

実際の質問ではありませんか?[**](https://meta.stackoverflow.com/q/284236/290085) – kjhughes

+0

あなたが試したことを教えてください。これまでのところ? –

答えて

2

あなたは私が2.0、より強力かつ、そのような作業に適してい を使用し、XSLTバージョンを指定しなかったよう。

スクリプトが含まれている必要があります

  • アイデンティティテンプレートを。
  • case_material要素のテンプレート。

このテンプレートは、必要があります。

  • option以外のすべての要素をコピーします。
  • option要素の特別な処理を提供します。

この特別な処理は、要素名でoption のすべての子要素のグループ化を含むべきです。あなたがすべきような各グループについて:

  • は、ソース要素の名前を持つ要素を作成します(キーのグループ化)。
  • すべてのグループメンバーの内容をカンマで区切って出力します。

は、私はあなたが特定の要素を(実際にのみ slug_value)「除外」したいことに気づいたので、ループは、それらを除外するための条件が含まれています。XSLT 1.0で、このようなスクリプトを記述することが可能である

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 

    <xsl:template match="case_material"> 
    <xsl:copy> 
     <xsl:apply-templates select="*[name() != 'option']|@*"/> 
     <xsl:for-each-group select="option/*" group-by="name()"> 
     <xsl:if test="current-grouping-key() != 'slug_value'"> 
     <xsl:element name="{current-grouping-key()}"> 
      <xsl:value-of select="current-group()" separator=","/> 
     </xsl:element> 
     </xsl:if> 
     </xsl:for-each-group> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="node()|@*"> 
    <xsl:copy><xsl:apply-templates select="node()|@*"/></xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

が、バージョン1.0にはないとして、あなたは は、より多くのコードを記述する必要があります:

だから、全体のスクリプトは以下のようになります。サポートグループ化。

+0

'except'演算子を使うと' * [name()!= 'option'] 'を' * except option'に短縮することができます。また、 'xsl:if'を' xsl:for-each-group select = "オプション/(* slug_valueを除く)" group-by = "name()"。 –

1

私はoption要素を除いてすべてをコピーしようとします。オプション要素を繰り返し、マージする必要がある項目をグループ化します。たとえば:

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

    <xsl:param name="pGroupElems" as="xs:string *" select="'value_local', 'value_en'" /> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()" /> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="case_material"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()" /> 
      <xsl:for-each-group select="option/*" group-by="local-name()[ . = $pGroupElems]"> 
       <xsl:copy> 
        <xsl:sequence select="string-join(current-group(), ',')" /> 
       </xsl:copy> 
      </xsl:for-each-group> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="option" /> 

</xsl:stylesheet> 
関連する問題