1

XSLT を使用して 2 つの兄弟ノードの値を結合しようとしています。既に同一のノードを組み合わせた XSLT シートを既に持っていますが、すでに配置されているものを台無しにせずに 2 つの兄弟ノードを組み合わせる方法を理解するのに苦労しています。

XML

<?xml version="1.0" encoding="UTF-8"?>
  <root xmlns:fm="http://www.filemaker.com/fmpdsoresult">
    <ROW xmlns="http://www.filemaker.com/fmpdsoresult">
      <Sign_Type>BB-1</Sign_Type>
      <fm:Floor xmlns="">1</fm:Floor>
      <fm:Location xmlns="">2</fm:Location>
      <Line1>ELEVATOR MACHINE ROOM 107</Line1>
    </ROW>
    <ROW xmlns="http://www.filemaker.com/fmpdsoresult">
      <Sign_Type>BB-1</Sign_Type>
      <fm:Floor xmlns="">1</fm:Floor>
      <fm:Location xmlns="">3</fm:Location>
      <Line1>ELEVATOR MACHINE ROOM 107</Line1>
    </ROW>
    <ROW xmlns="http://www.filemaker.com/fmpdsoresult">
      <Sign_Type>BB-1</Sign_Type>
      <fm:Floor xmlns="">1</fm:Floor>
      <fm:Location xmlns="">4</fm:Location>
      <Line1>ELEVATOR MACHINE ROOM 107</Line1>
    </ROW>
    <ROW xmlns="http://www.filemaker.com/fmpdsoresult">
      <Sign_Type>BB-1</Sign_Type>
      <fm:Floor xmlns="">1</fm:Floor>
      <fm:Location xmlns="">5</fm:Location>
      <Line1>ELEVATOR MACHINE ROOM 107</Line1>
    </ROW>
  </root>

XSL

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fm="http://www.filemaker.com/fmpdsoresult">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="artTypeNames" match="fm:ROW" use="concat(fm:Sign_Type, '||', fm:Line1)"/>
 <xsl:template match="fm:FMPDSORESULT">
    <ROOT>
        <xsl:apply-templates select="fm:ROW[count(. | key('artTypeNames', concat(fm:Sign_Type, '||', fm:Line1))[1]) = 1]">
            <xsl:sort select="fm:Sign_Type" />
        </xsl:apply-templates>
    </ROOT>
 </xsl:template>

 <xsl:template match="fm:ROW">
        <xsl:copy>
            <xsl:apply-templates select="fm:Sign_Type" />

            <fm:Location>
                <xsl:apply-templates select="key('artTypeNames', concat(fm:Sign_Type,   '||', fm:Line1))/fm:Location" /> 
            </fm:Location>
            <xsl:apply-templates select="fm:Line1" />
        </xsl:copy>
</xsl:template>

<xsl:template match="fm:Location">
    <xsl:if test="position() &gt; 1">, </xsl:if>
    <xsl:value-of select="." />
</xsl:template>

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

</xsl:stylesheet>   

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

 <?xml version="1.0" encoding="UTF-8"?>
  <root xmlns:fm="http://www.filemaker.com/fmpdsoresult">
    <ROW xmlns="http://www.filemaker.com/fmpdsoresult">
      <Sign_Type>BB-1</Sign_Type>
      <fm:Location xmlns="">1-2, 1-3, 1-4, 1-5</fm:Location>
      <Line1>ELEVATOR MACHINE ROOM 107</Line1>
    </ROW>
  </root>

これを機能させるためにどこを何を変更する必要があるかを特定するのを手伝ってくれる人はいますか? ありがとう!

4

1 に答える 1

1

コードの単なるタイプミスかもしれませんが、最初のテンプレートは要素FMPDSORESULTに一致しますが、これは XML サンプルには存在しません!

<xsl:template match="fm:FMPDSORESULT">

これは何にも一致しないため、組み込みのテンプレートが適用され、最終的に XMLの 4 つのROW要素のそれぞれに対してfm:ROWに一致するテンプレートが使用されます。

ルート要素で一致する必要があります

<xsl:template match="root">

兄弟の結合については、 Floor要素をLocation要素と一緒に出力したいとおっしゃっていると思います。たとえば、ここでは先行兄弟を使用できます。

<xsl:value-of select="preceding-sibling::fm:Floor[1]" />

あるいは、この構文も機能します。現在の親の唯一のフロア要素を取得するだけです

<xsl:value-of select="../fm:Floor" />

このXSLTを試してください

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fm="http://www.filemaker.com/fmpdsoresult">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="artTypeNames" match="fm:ROW" use="concat(fm:Sign_Type, '||', fm:Line1)"/>
 <xsl:template match="root">
    <ROOT>
        <xsl:apply-templates select="fm:ROW[count(. | key('artTypeNames', concat(fm:Sign_Type, '||', fm:Line1))[1]) = 1]">
            <xsl:sort select="fm:Sign_Type" />
        </xsl:apply-templates>
    </ROOT>
 </xsl:template>

 <xsl:template match="fm:ROW">
        <xsl:copy>
            <xsl:apply-templates select="fm:Sign_Type" />

            <fm:Location>
                <xsl:apply-templates select="key('artTypeNames', concat(fm:Sign_Type,   '||', fm:Line1))/fm:Location" /> 
            </fm:Location>
            <xsl:apply-templates select="fm:Line1" />
        </xsl:copy>
</xsl:template>

<xsl:template match="fm:Location">
    <xsl:if test="position() &gt; 1">, </xsl:if>
    <xsl:value-of select="../fm:Floor" />
    <xsl:text>-</xsl:text>
    <xsl:value-of select="." />
</xsl:template>

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>   
于 2013-11-12T08:38:34.297 に答える