2016-10-20 7 views
0

「SmallCat」や「BigCat」などのタイプの複数の子を含むXML文書の部分を効率的に再編成する方法を探しています。ここで条件付きXML再編成

はルールがあります:生息地のノードを除く

  1. すべてが通過しなければなりません。属性とすべて。
  2. BigCatまたはSmallCatのインスタンスが2つ未満の生息地ノードを通過させる必要があります。

入力された文書には、次のようになります。

<Zoo> 
    <Habitat HabitatID="habitat.cage.1"> 
    <Type>Cats</Type> 
    <Food>Birds</Food> 
    <BigCat AnimalID="Tiger.1"> 
     <Type>Bengal</Type> 
    </BigCat> 
    <SmallCat AnimalID="bobcat.1"> 
     <Type>Bobcat</Type> 
    </SmallCat> 
    <BodyTemp>endothermic</BodyTemp> 
    </Habitat> 
    <Habitat HabitatID="cage.2"> 
    <Type>Cats</Type> 
    <Food>Birds</Food> 
    <SmallCat AnimalID="tabycat.1"> 
     <Type>Tabycat</Type> 
    </SmallCat> 
    <BodyTemp>endothermic</BodyTemp> 
    </Habitat> 
    <ConsessionStand> 
    <Type>PopcornStand</Type> 
    </ConsessionStand> 
</Zoo> 

出力は次のようになります。

<Zoo> 
    <Habitat HabitatID="sub_habitat.1.habitat.cage.1"> 
    <Type>Cats</Type> 
    <Food>Birds</Food> 
    <BigCat AnimalID="Tiger.1"> 
     <Type>Bengal</Type> 
    </BigCat> 
    </Habitat> 

    <Habitat HabitatID="sub_habitat.2.habitat.cage.1"> 
    <Type>Cats</Type> 
    <Food>Birds</Food> 
    <SmallCat AnimalID="bobcat.1"> 
     <Type>Bobcat</Type> 
    </SmallCat> 
    </Habitat> 

    <Habitat HabitatID="habitat.cage.1"> 
    <BodyTemp>endothermic</BodyTemp> 
    <Child> 
     <HabitatID>sub_habitat.1.habitat.cage.1</HabitatID> 
    </Child> 
    <Child> 
     <HabitatID>sub_habitat.2.habitat.cage.1</HabitatID> 
    </Child> 
    </Habitat> 

    <Habitat HabitatID="cage.2"> 
    <Type>Cats</Type> 
    <Food>Birds</Food> 
    <SmallCat AnimalID="tabycat.1"> 
     <Type>Tabycat</Type> 
    </SmallCat> 
    <BodyTemp>endothermic</BodyTemp> 
    </Habitat> 
    <ConsessionStand> 
    <Type>PopcornStand</Type> 
    </ConsessionStand> 
</Zoo> 

理想的なソリューションは、XSLTを使用しますが、任意の溶液(bashのは、Javascript、PHP、Pythonのだろう、ルビー、ゴー、など)は、仕事を完了するためには合理的な候補です。

ここには、約90%の作業を行う実装があります。

このソリューションは、新しいsub_habitat子ノードへの参照を持つ最初の生息地ノードを再構築しません。

<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="Habitat[count(BigCat|SmallCat) &gt; 1]"> 
     <xsl:param name="i"/> 
     <xsl:for-each select="BigCat|SmallCat"> 
      <xsl:choose> 
      <xsl:when test="self::BigCat"> 
       <Habitat HabitatID="sub_habitat.{position()}.{../@HabitatID}"> 
       <xsl:copy-of select="../*[not(self::SmallCat|self::BodyTemp)]"/> 
       </Habitat> 
      </xsl:when> 
      <xsl:when test="self::SmallCat"> 
       <Habitat HabitatID="sub_habitat.{position()}.{../@HabitatID}"> 
       <xsl:copy-of select="../*[not(self::BigCat|self::BodyTemp)]"/> 
       </Habitat> 
      </xsl:when> 
      </xsl:choose> 
     </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

出力結果はここに表示されます。

<Zoo> 
    <Habitat HabitatID="sub_habitat.1.habitat.cage.1"> 
    <Type>Cats</Type> 
    <Food>Birds</Food> 
    <BigCat AnimalID="Tiger.1"> 
     <Type>Bengal</Type> 
    </BigCat> 
    </Habitat> 
    <Habitat HabitatID="sub_habitat.2.habitat.cage.1"> 
    <Type>Cats</Type> 
    <Food>Birds</Food> 
    <SmallCat AnimalID="bobcat.1"> 
     <Type>Bobcat</Type> 
    </SmallCat> 
    </Habitat> 
    <Habitat HabitatID="cage.2"> 
    <Type>Cats</Type> 
    <Food>Birds</Food> 
    <SmallCat AnimalID="tabycat.1"> 
     <Type>Tabycat</Type> 
    </SmallCat> 
    <BodyTemp>endothermic</BodyTemp> 
    </Habitat> 
    <ConsessionStand> 
    <Type>PopcornStand</Type> 
    </ConsessionStand> 
</Zoo> 
+0

を持っていますか? –

+0

@ Michael.hor257k:まず、この問題はXSLTを使用して解決できますか?私は意味のある例を示すのに十分な専門家ではない。第二に、もしそうなら、誰かが実用的な例を提供することができます。第三に、XSLTを使用して問題を解決できない場合、他の言語では最適なソリューションはどのように見えますか? – Amvoxite

+0

"*この問題はXSLTを使用して解決できますか?*"私はできると信じていますが、これはコード作成サービスではありません。 –

答えて

0

何を試しましたか?あなたの産物の問題の説明の各ルールは、かなり直接テンプレートルールに変換されます。たとえば、ルール:

この経験は、1つの以上の要素(視聴覚と ギャラリー)が含まれて2離散経験のセット 子供

のようなものになると、それが再編成されます
<xsl:template match="Experience[count(Audiovisual|Gallery) gt 1]"> 
    <xsl:for-each select="AudioVisual|Gallery"> 
    <Experience ExperienceID="{../@ExperienceID}.ce.{position()}"/> 
     <xsl:copy-of select="../*[not(self::AudioVisual|self::Gallery)]"/> 
     <xsl:copy-of select="."/> 
    </Experience> 
    </xsl:for-each> 
</xsl:template> 

すべてのルールを確認し、それぞれのルールを作成してください。

+0

プロセッサが各エクスペリエンスのルールを呼び出すと、2つの副作用が予想されます。 1つは、個別のオーディオビジュアルまたはギャラリータイプ用の新しいエクスペリエンスノードの作成です。 – Amvoxite

+0

XSLT処理モデルの完全な誤解を示しているのではないかと恐れていますテンプレートルールには、結果を返します。結果として、結果ツリーが作成されます。テンプレートルールはその結果ツリーの一部を構成できますが、2つの異なる部分を構築することはできません。 –

+0

ありがとう、マイク。悲しいかな、XSLTでその洗練されたレベルのソリューションを実装しているのは率直にも私が助けを求めている理由です。 – Amvoxite

0

は以下のスタイルシート考えてみましょう:

XSLTご入力の例に適用1.0

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

<xsl:template match="/Zoo"> 
    <xsl:copy> 
     <xsl:apply-templates select="Habitat/BigCat | Habitat/SmallCat"/> 
     <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="BigCat| SmallCat"> 
    <Habitat HabitatID="sub_habitat.{position()}.{../@HabitatID}"> 
     <xsl:copy-of select="../*[not(self::BigCat or self::SmallCat or self::BodyTemp)]"/> 
     <xsl:copy-of select="."/> 
    </Habitat> 
</xsl:template> 

<xsl:template match="Habitat"> 
    <xsl:copy> 
     <xsl:copy-of select="@* | BodyTemp"/> 
     <xsl:apply-templates select="BigCat | SmallCat" mode="child"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="BigCat| SmallCat" mode="child"> 
    <Child> 
     <HabitatID> 
      <xsl:text>sub_habitat.</xsl:text> 
      <xsl:value-of select="position()"/> 
      <xsl:text>.</xsl:text> 
      <xsl:value-of select="../@HabitatID"/> 
     </HabitatID> 
    </Child> 
</xsl:template> 

</xsl:stylesheet> 

を、結果は以下のようになります。あなたは、実際の質問を

<?xml version="1.0" encoding="UTF-8"?> 
<Zoo> 
    <Habitat HabitatID="sub_habitat.1.habitat.cage.1"> 
     <Type>Cats</Type> 
     <Food>Birds</Food> 
     <BigCat AnimalID="Tiger.1"> 
     <Type>Bengal</Type> 
     </BigCat> 
    </Habitat> 
    <Habitat HabitatID="sub_habitat.2.habitat.cage.1"> 
     <Type>Cats</Type> 
     <Food>Birds</Food> 
     <SmallCat AnimalID="bobcat.1"> 
     <Type>Bobcat</Type> 
     </SmallCat> 
    </Habitat> 
    <Habitat HabitatID="habitat.cage.1"> 
     <BodyTemp>endothermic</BodyTemp> 
     <Child> 
     <HabitatID>sub_habitat.1.habitat.cage.1</HabitatID> 
     </Child> 
     <Child> 
     <HabitatID>sub_habitat.2.habitat.cage.1</HabitatID> 
     </Child> 
    </Habitat> 
</Zoo> 
+0

これはかなり近いです! SmallcatまたはBigCatのタイプが1つだけのHabitatのインスタンスは通過する必要があります。したがって、元の制約の一致= 'Habitat [count(BigCat | SmallCat)> 1]'です。 – Amvoxite

+0

@Amvoxiteこれは、適用する必要がある**ルール**を説明せずに例文を投稿するときに起こります。あなたの事例では、「ハビタットのインスタンスはSmallCatやBigCatの1つしかありません。」とはいえ、とにかく自分でこれを終えるだけの十分な能力を持っていると思いますが、そう思わないのですか? –

+0

さて、初心者の投稿をお考えください。多分私はXSLTをあきらめるべきです... – Amvoxite