inDesign XML XSLT 自動化 データ更新

inDesignの構造（XML）でXSLTを使ってデータの更新を自動化するのは、これで良いのかな？

↓構造のXML（見やすくしてあります）

~~~xml:構造.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root>
    <Story>
        <Code>02-0000</Code>
        <Name>猫</Name>
        <Price>0</Price>
        <Price2>0</Price2>
    </Story>
    <Information>
        <Story>
            <Code>03</Code>
            <Name>熊</Name>
            <Price>0</Price>
            <Price2>0</Price2>
        </Story>
        <Image href="file:///test.psd"></Image>
    </Information>
</Root>
~~~

↓ 更新用のXSLT、参照する要素の値が「-」等で区切られていて複数ある場合や階層が異なっている場合にも対応。

~~~xml:XSLT_更新用.xsl
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE MyXSLEntity [

<!-- 参照する要素。 文字にする為「'」で囲む -->
<!ENTITY referenceElement "'Code'">

<!-- 更新する要素。複数条件がある場合は|で区切り追加 -->
<!ENTITY updateElement "Price|Price2">

<!-- このxslファイルの場所を基準に指定した更新用情報源xmlファイル -->
<!ENTITY sourceXML "source.xml">
]>

<!--
このXSLを利用して起こった不具合の責任は取れません。
ご了承下さい。

更新 2022/06/17
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" encoding="UTF-8" standalone="yes"/>
    <xsl:variable name="source" select="document('&sourceXML;')"/>
    <xsl:template match="*">
        <xsl:copy>
            <xsl:choose>
                <!-- 参照する要素を子を持つ要素の場合-->
                <xsl:when test="./*[name() = &referenceElement;]">
                    <!-- 参照する要素の値が複数か -->
                    <xsl:choose>
                        <xsl:when test="contains(./*[name()=&referenceElement;], '-')">
                            <xsl:attribute name="note">
                                <xsl:value-of select="'multi(-)'"/>
                            </xsl:attribute>
                            <!-- 更新処理テンプレート呼び出し -->
                            <xsl:call-template name="updateProcess">
                                <xsl:with-param name="referenceValue" select="substring-before(./*[name()=&referenceElement;], '-')"/>
                            </xsl:call-template>
                        </xsl:when>
                        <xsl:when test="contains(./*[name()=&referenceElement;], '/')">
                            <xsl:attribute name="note">
                                <xsl:value-of select="'multi(/)'"/>
                            </xsl:attribute>
                            <xsl:call-template name="updateProcess">
                                <xsl:with-param name="referenceValue" select="substring-before(./*[name()=&referenceElement;], '/')"/>
                            </xsl:call-template>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:attribute name="note">
                                <xsl:value-of select="'single'"/>
                            </xsl:attribute>
                            <xsl:call-template name="updateProcess">
                                <xsl:with-param name="referenceValue" select="./*[name()=&referenceElement;]"/>
                            </xsl:call-template>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:when>
                <xsl:otherwise>
                    <!-- 子を持つ要素-->
                    <xsl:apply-templates select="*[./*]"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:copy>
    </xsl:template>
    <!-- 更新処理テンプレート 参照の値が複数ある場合は最初の値で参照-->
    <xsl:template name="updateProcess">
        <xsl:param name="referenceValue"/>
        <!-- 参照する要素名でかつ内容が同じ要素が見つかった場合（更新される場合）か -->
        <xsl:choose>
            <xsl:when test="$source//*[name()=&referenceElement;][text()=$referenceValue]">
                <xsl:attribute name="update">
                    <xsl:value-of select="'finish'"/>
                </xsl:attribute>
                <xsl:for-each select="&updateElement;">
                    <!-- 現在の要素名 -->
                    <xsl:variable name="elementName" select="name()"/>
                    <xsl:copy>
                        <xsl:value-of select="$source//*[name()=&referenceElement;][text()=$referenceValue]/../*[name()=$elementName]"/>
                    </xsl:copy>
                </xsl:for-each>
            </xsl:when>
            <xsl:otherwise>
                <xsl:attribute name="update">
                    <xsl:value-of select="'unfinish'"/>
                </xsl:attribute>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>
~~~

↓ 更新用ソースXML（見やすくしてあります）

~~~xml:source.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root>
    <Spec>
        <Code>01</Code>
        <Name>犬</Name>
        <Price>100</Price>
        <Price2>110</Price2>
    </Spec>
    <Spec>
        <Code>02</Code>
        <Name>猫</Name>
        <Price>200</Price>
        <Price2>220</Price2>
    </Spec>
    <Spec>
        <Code>03</Code>
        <Name>熊</Name>
        <Price>300</Price>
        <Price2>330</Price2>
    </Spec>
    <Spec>
        <Code>04</Code>
        <Name>ペンギン</Name>
        <Price>400</Price>
        <Price2>440</Price2>
    </Spec>
</Root>
~~~

構造のメニューの「XMLを書き出し...」の
「XSLTを適用」で更新用のxslを選択
「エンコーディング」はUTF-8で書き出す。

↓ 書き出し後のXML（見やすくしてあります）

~~~xml:書き出し後.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root>
    <Story note="multi(-)" update="finish">
        <Price>200</Price>
        <Price2>220</Price2>
    </Story>
    <Information>
        <Story note="single" update="finish">
            <Price>300</Price>
            <Price2>330</Price2>
        </Story>
    </Information>
</Root>
~~~

構造のメニューの「XMLを読み込み...」のXML読み込みオプションで
「内容を結合」
「空白のみの要素を読み込まない」
で先ほど書き出したXMLを読み込み。

↓読み込み後のXML、Price、Price2要素が更新、参照値の単複と更新結果を属性として保存。

~~~xml:読み込み後.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root>
    <Story note="multi(-)" update="finish">
        <Code>02-0000</Code>
        <Name>猫</Name>
        <Price>200</Price>
        <Price2>220</Price2>
    </Story>
    <Information>
        <Story note="single" update="finish">
            <Code>03</Code>
            <Name>熊</Name>
            <Price>300</Price>
            <Price2>330</Price2>
        </Story>
        <Image href="file:///test.psd"></Image>
    </Information>
</Root>
~~~

「検索と置換」の正規表現の検索文字列に「.+」と検索形式にスタイル等々、置換形式にXMLで置換すると改行を除いて要素に出来ます。
改行を除いて要素にしておくと要素の内容が変更されても段落スタイルは維持されます。
文字スタイルは段落スタイルの正規表現スタイル等で付けて下さい。