2

2 つの列に基づく FK を持つ XML 形式で格納された DB テーブルがあります (Table2 には ID と TYPE に基づく Table1 への FK があります)。


    Table1.xml
    <Table>
       <Row>
          <ID>1</ID>
          <TYPE>A</TYPE>
          <CONFIG>Y</CONFIG>
          ...
       </Row>
       <Row>
          <ID>2</ID>
          <TYPE>A</TYPE>
          <CONFIG>Z</CONFIG>
          ...
       </Row>
       <Row>
          <ID>1</ID>
          <TYPE>B</TYPE>
          <CONFIG>X</CONFIG>
          ...
       </Row>
       <Row>
          <ID>3</ID>
          <TYPE>A</TYPE>
          <CONFIG>Z</CONFIG>
          ...
       </Row>
    </Table>

    Table2.xml
    <Table>
       <Row>
          <ID>1</ID>
          <TYPE>A</TYPE>
          ...
       </Row>
       <Row>
          <ID>2</ID>
          <TYPE>A</TYPE>
          ...
       </Row>
       <Row>
          <ID>1</ID>
          <TYPE>B</TYPE>
          ...
       </Row>
       <Row>
          <ID>3</ID>
          <TYPE>A</TYPE>
          ...
       </Row>
    </Table>


各 XML ファイルの行を削除するための 2 つの XSLT ファイルがあります。Table2 が最初に処理されます。Table1 CONFIG=Z と結合したときに Table2 の行を削除したい (つまり、(ID=2 および Type=A) および (ID=3 および Type=A) の行を削除しますが、これだけを把握する必要があります。 CONFIG=Z のレコードを削除したいことを知っている)。次に、テーブル 1 が処理されて、CONFIG=Z の行が削除されます。これは私が把握できました。

Table2 に適用される XSLT は、Table1 XML (xsl:variable name="table1Rows" select="document('Table1.xml')/Table/Row"/>) を読み込む必要があると思います。その後、CONFIG=Z である Table2 の行を削除する方法がわかりません。見た例に基づいていくつかのことを試しましたが、何も機能しませんでした。

4

3 に答える 3

0

マーティンによって提供された答えは機能し、おそらく可能な限り最良の解決策です。XSLT 1.0の場合、より高速に実行されるように見えますが、それほどエレガントではない次のことを思いつきました。このソリューションでは、CONFIG=Zで可能なTYPEは「A」のみであることがわかりました。(XSLTを別のマシンで実行していて、ここでモック列の名前/値を使用して再入力したため、以下のタイプミスがある可能性があることに注意してください。)


    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
         <xsl:variable name="table1_Z_rows" select="document('table1.xml')/Table/Row[CONFIG='Z']"/>
             <xsl:template match="Row">
                  <xsl:choose>
                       <xsl:when test="TYPE != 'A'">
                            <xsl:copy-of select="."/>
                       </xsl:when>
                       <xsl:otherwise>
                           <xsl:if test="not(ID = $table1_Z_rows/ID)">
                                <xsl:copy-of select="."/>
                           </xsl:if>
                       </xsl:otherwise>
                  </xsl:choose>
             </xsl:template>
        </xsl:stylesheet>

于 2012-10-02T14:16:09.893 に答える
0

RowXSLT 2.0 を使用してキーを定義し、要素を相互参照してから、単純に恒等変換を実行してノードをコピーするだけでなく、キー関数呼び出しが他のドキュメントで CONFIG を使用して行を見つけた場合、それらの要素のコピーを抑制するテンプレートを追加しますZ

<xsl:variable name="table1" select="doc('Table1.xml')"/>

<xsl:key name="r-by-id-and-type" match="Table/Row" use="concat(ID, '|', TYPE)"/>

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

<xsl:template match="Row[key('r-by-id-and-type', concat(ID, '|', TYPE), $table1)/CONFIG = 'Z']"/>

[編集] 完全を期すために、Saxon 9.4 と AltovaXML の両方で次の完全なサンプルをテストしました。

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">

<xsl:variable name="table1" select="doc('table1.xml')"/>

<xsl:key name="r-by-id-and-type" match="Table/Row" use="concat(ID, '|', TYPE)"/>

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

<xsl:template match="Row[key('r-by-id-and-type', concat(ID, '|', TYPE), $table1)/CONFIG = 'Z']"/>

</xsl:stylesheet>

コメントのリクエストに応じて、XSLT 1.0 スタイルシートも追加します。

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

<xsl:variable name="table1" select="document('test2012100102.xml')"/>

<xsl:key name="r-by-id-and-type" match="Table/Row" use="concat(ID, '|', TYPE)"/>

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

<xsl:template match="Row">
  <xsl:variable name="this" select="."/>
  <xsl:for-each select="$table1">
    <xsl:if test="not(key('r-by-id-and-type', concat($this/ID, '|', $this/TYPE))/CONFIG = 'Z')">
      <xsl:copy-of select="$this"/>
    </xsl:if>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>
于 2012-10-01T17:25:47.253 に答える
0

元の質問を考えると、マーティンの解決策は正しく、受け入れられるべきです。

追加の XSLT 1.0 ソリューションに対する OP の要求を参照して、ここにポリグロットがあります。このスタイルシートは、Martin のソリューションのマイナー バリエーションであり、XSLT 2.0 プロセッサと、おそらくほとんどの XSLT 1.0 プロセッサで動作します。

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">

<xsl:variable name="table1" select="doc('table1.xml')"/>

<xsl:key name="r-by-id-and-type" match="Table/Row" use="concat(ID, '|', TYPE)"/>

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

<xsl:template
  match="Row"
  use-when="number(system-property('xsl:version')) &lt; 2" priority="2">
    <xsl:variable name="row" select="." />
    <xsl:variable name="id-type" select="concat(ID, '|', TYPE)" />
    <xsl:for-each select="$table1">
      <xsl:if test="not( key('r-by-id-and-type', $id-type))">
        <xsl:for-each select="$row">
          <xsl:call-template name="ident" />
        </xsl:for-each>
      </xsl:if> 
    </xsl:for-each>
</xsl:template>

<xsl:template
  match="Row"
  use-when="number(system-property('xsl:version')) &gt;= 2" priority="1">
    <xsl:if test="not( key('r-by-id-and-type', concat(ID, '|', TYPE), $table1))">
      <xsl:call-template name="ident" />
    </xsl:if> 
</xsl:template>
</xsl:stylesheet>

警告

このスタイルシートはテストされていません。

于 2012-10-02T03:56:06.533 に答える