2

属性の違い (新しい属性ノードではなく更新のみ) について 2 つの XML ドキュメントを比較し、属性と属性の新しい値への XPath ポインターのセットを生成するコードがあります。

セットアップ

たとえば、古い XML と新しい XML があるとします。

古い XML

<EntityA>
  <EntityB id="foo1" value="bar1" ignoredbutsave="bazz1"/>
</EntityA>

新しい XML

<EntityA>
  <EntityB id="foo2" value="bar2"/>
</EntityA>

私のコードは戻ります

/EntityA/EntityB/@id, foo2
/EntityA/EntityB/@value, bar2

古い XML を新しい XML にマージする XSLT を生成して、次の XML を作成したいと考えています。

<EntityA>
  <EntityB id="foo2" value="bar2" ignoredbutsave="bazz1"/>
</EntityA>

SOで見つけたすべての回答は、属性名に関する事前の知識を前提としています。この場合、名前自体ではなく、属性の XPath 参照のみが与えられます。XPath 文字列を解析して属性名を取得できることはわかっていますが、その複雑さをコードから除外したいと考えています。

私が試したこと

古い XML から属性をコピーする必要があるため、属性値テンプレートを使用できません。ignoredbutsave次のように、xsl:param を使用して XPath から属性名を選択し、xsl:attribute 内で使用しようとしました。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes"/>

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

  <xsl:template match="/EntityA/EntityB/@id">
    <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
       <xsl:param name="newValue" select="name(/EntityA/EntityB/@id)"/>
         <xsl:attribute name="$newValue">newAttributeId</xsl:attribute>
     </xsl:copy>
  </xsl:template>

  <xsl:template match="/EntityA/EntityB/@value">
    <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
       <xsl:param name="myattrname" select="name(/EntityA/EntityB/@value)"/>
         <xsl:attribute name="$myattrname">newAttributeValue</xsl:attribute>
     </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

ただし、これによりエラーが発生しますThe value '$myattrname' of the attribute 'name' is not a valid QName.

属性の XPath とその属性の新しい値が与えられた場合、属性名を明示的に参照せずにその値を更新する XSLT を生成するにはどうすればよいでしょうか?

4

1 に答える 1

1

この XSLT 変換:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes"/>

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

  <xsl:template match="/EntityA/EntityB/@id">
    <xsl:attribute name="{name()}">foo2</xsl:attribute>
  </xsl:template>

  <xsl:template match="/EntityA/EntityB/@value">
    <xsl:attribute name="{name()}">bar2</xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

古い XML に適用:

<EntityA>
  <EntityB id="foo1" value="bar1" ignoredbutsave="bazz1"/>
</EntityA>

必要な属性値の置換が行われた古い XML を生成します。

<EntityA>
  <EntityB id="foo2" value="bar2" ignoredbutsave="bazz1"/>
</EntityA>
于 2013-10-24T23:50:37.117 に答える