0

そこで、php curl 応答から生成した XML ファイルを取得しました。このファイルは、以下の各 mods 要素が 1 行になるように CSV に変換されます。チェック済みの回答hereのスタイルシートを使用して CSV をいくつか持っていますが、それは私がやろうとしていることではありません。

私のXML(簡略化):

<xml>
<mods xmlns="http://www.loc.gov/mods/">
      <typeOfResource>StillImage</typeOfResource>
      <titleInfo ID="T-1">
        <title>East Bay Street</title>
      </titleInfo>
      <subject ID="SBJ-2">
        <topic>Railroads</topic>
      </subject>
      <subject ID="SBJ-3">
        <geographic>Low Country</geographic>
      </subject>
      <subject ID="SBJ-4">
        <geographic>Charleston (S.C.)</geographic>
      </subject>
      <subject ID="SBJ-7">
        <hierarchicalGeographic>
          <county>Charleston County (S.C.)</county>
        </hierarchicalGeographic>
      </subject>
      <physicalDescription>
        <form>Images</form>
      </physicalDescription>
      <note>Caption: &apos;War Views. No.179.  Ruins of the Northeastern Railway Depot, Charleston.&apos;  This is a stereograph image which measures 3 1/2&quot; X 7&quot;.  Date assumed to be 1865.</note>
      <originInfo>
        <dateCreated>1865</dateCreated>
      </originInfo>
      <location>
        <physicalLocation>The Charleston Museum Archives</physicalLocation>
      </location>
      <relatedItem type="host">
        <titleInfo>
          <title>Charleston Museum Civil War Photographs</title>
        </titleInfo>
      </relatedItem>
    </mods>

   <mods>
     more nodes...
   </mods>
</xml>

上記のスタック投稿からの現在の XSL:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="iso-8859-1"/>

<xsl:strip-space elements="*" />

<xsl:template match="/*/child::*">
<xsl:for-each select="child::*">
<xsl:if test="position() != last()"><xsl:value-of select="normalize-space(.)"/>,        </xsl:if>
<xsl:if test="position()  = last()"><xsl:value-of select="normalize-space(.)"/>    <xsl:text>&#xD;</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>

 </xsl:stylesheet>

これにより、各 MODS 要素が 1 行であり、各子がその行のコンマ区切りの値である CSV が出力されます。各 MODS 要素が 1 行になるように XSL を変更できますが、一致する子の値はグループ化されますか? 何かのようなもの:

StillImage,East Bay Street,Railroads,**Low County;Charleston (S.C.)**,Charleston County (S.C.), Images

.......等々。

ノード (複数のサブジェクト -> 地理的エントリなど) が一致する場合、それらはグループ化され、複数のカンマ区切りの値を使用するのではなく、セミコロンで区切られますか? うまくいけば、私はいくつかの意味を成しています。ありがとう!

4

1 に答える 1

2

これを行う1つの方法は、最初にXSLTを変更して、同じ子名を持つ先行兄弟を持たない要素のみを選択することです(つまり、各グループで「最初」の要素を選択します)。

<xsl:for-each select="*[name(*) != name(preceding-sibling::*[1]/*)]">

次に、変数を定義して、同じ名前の場合 (およびその場合にのみ)、次の兄弟を取得できるため、現在の要素が実際に複数のグループに含まれているかどうかを確認できます。

<xsl:variable name="nextWithSameName" 
              select="following-sibling::*[1][name(*)=name(current()/*)]"/>
<xsl:if test="$nextWithSameName">**</xsl:if>

(実際に最終結果に ** が必要なのか、それともグループを強調するためだけにあるのかはわかりません! 例ではそれらを保持していますが、明らかに関連するコード行を削除するのは簡単です。 )。

次の兄弟を同じ名前でグループ化するには、最初の次の兄弟の再帰テンプレートを呼び出すことができます

<xsl:apply-templates select="$nextWithSameName" mode="group"/>

次に、このテンプレート内で、直後の兄弟が同じ名前を持つ場所で再帰的に呼び出します。

<xsl:template match="*" mode="group">
   <xsl:text>;</xsl:text>
   <xsl:value-of select="normalize-space(.)"/>
   <xsl:apply-templates select="following-sibling::*[1][name(*)=name(current()/*)]" />
</xsl:template>

次の XSLT を試してください

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="text" encoding="iso-8859-1"/>
   <xsl:strip-space elements="*"/>

   <xsl:template match="/*/*">
      <xsl:for-each select="*[name(*) != name(preceding-sibling::*[1]/*)]">
         <xsl:variable name="nextWithSameName" select="following-sibling::*[1][name(*)=name(current()/*)]"/>
         <xsl:if test="position() &gt; 1">,    </xsl:if>
         <xsl:if test="$nextWithSameName">**</xsl:if>
         <xsl:value-of select="normalize-space(.)"/>
         <xsl:apply-templates select="$nextWithSameName" mode="group"/>
         <xsl:if test="$nextWithSameName">**</xsl:if>
      </xsl:for-each>
      <xsl:text>&#xD;</xsl:text>
   </xsl:template>

   <xsl:template match="*" mode="group">
      <xsl:text>;</xsl:text>
      <xsl:value-of select="normalize-space(.)"/>
      <xsl:apply-templates select="following-sibling::*[1][name(*)=name(current()/*)]" />
   </xsl:template>
</xsl:stylesheet>

ここで、XSLT 2.0 を使用できれば、'group-adjacent' への操作が付属するxsl:for-each-groupコンストラクトを使用できるため、作業がはるかに簡単になります。また、改良されたxsl:value-ofを使用して、再帰的なテンプレートを廃止することもできます。これには、複数の要素が選択されているときに使用する「区切り」プロパティがあります。

XSLT 2.0 の場合、以下も機能するはずです。

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" encoding="iso-8859-1"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/*/*">
        <xsl:for-each-group select="*" group-adjacent="name(*)">
            <xsl:if test="position() &gt; 1">,    </xsl:if>
            <xsl:if test="current-group()[2]">**</xsl:if>
            <xsl:value-of select="current-group()" separator=";" />
            <xsl:if test="current-group()[2]">**</xsl:if>
        </xsl:for-each-group >
        <xsl:text>&#xD;</xsl:text>
    </xsl:template>
</xsl:stylesheet>
于 2013-10-12T08:26:54.097 に答える