Xslt 删除外键

Xslt 删除外键,xslt,xslt-2.0,Xslt,Xslt 2.0,我有一些以XML格式存储的DB表,它们有一个基于两列的FK(表2有一个基于ID和类型的FK到表1) 表1.xml 1. A. Y ... 2. A. Z ... 1. B X ... 3. A. Z ... 表2.xml 1. A. ... 2. A. ... 1. B ... 3. A. ... 我将有两个XSLT文件来删除每个XML文件中的行。表2将首先处理。我想删除Table2中的行,其中与Table1 CONFIG=Z连接时(即,删除其中的行(ID=2,Type=A)和(ID=3,T

我有一些以XML格式存储的DB表,它们有一个基于两列的FK(表2有一个基于ID和类型的FK到表1)


表1.xml
1.
A.
Y
...
2.
A.
Z
...
1.
B
X
...
3.
A.
Z
...
表2.xml
1.
A.
...
2.
A.
...
1.
B
...
3.
A.
...
我将有两个XSLT文件来删除每个XML文件中的行。表2将首先处理。我想删除Table2中的行,其中与Table1 CONFIG=Z连接时(即,删除其中的行(ID=2,Type=A)和(ID=3,Type=A),但我只需要知道我想删除CONFIG=Z的记录就可以解决这个问题。然后,将处理表1以删除CONFIG=Z的行,这是我能够理解的


我认为将应用于表2的XSLT需要读入表1 XML(xsl:variable name=“table1Rows”select=“document('Table1.XML')/Table/Row”/>)。在那之后,我就不知道如何删除Table2中CONFIG=Z的行了。我根据看到的示例尝试了一些方法,但都没有成功。

使用XSLT 2.0定义一个键并交叉引用元素,然后,只需执行标识转换,以复制节点和一个模板,该模板禁止复制那些
元素,其中键函数调用在另一个文档中找到配置为
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']"/>

[edit]为了完整性,我使用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>

使用XSLT 2.0定义一个键并交叉引用元素,然后简单地执行标识转换以复制节点和一个模板,该模板禁止复制那些
元素,其中键函数调用在另一个文档中找到配置为
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']"/>

[edit]为了完整性,我使用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>

考虑到原始问题,Martin的解决方案是正确的,应该被接受

关于OP对附加XSLT1.0解决方案的请求,这里有一个多语言的例子。此样式表是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>

警告
此样式表未经测试。

考虑到原始问题,Martin的解决方案是正确的,应该接受

关于OP对附加XSLT1.0解决方案的请求,这里有一个多语言的例子。此样式表是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>

警告
此样式表未经测试。

Martin提供的答案有效,可能是最好的解决方案。对于XSLT1.0,我提出了以下内容,它似乎运行得更快,但没有那么优雅。对于这个解决方案,我知道CONFIG=Z的唯一可能类型是“A”。(注意,下面可能有输入错误,因为我在另一台机器上运行XSLT,并在这里用模拟列名/值重新键入。)



Martin提供的答案有效,可能是最好的解决方案。对于XSLT1.0,我提出了以下内容,它似乎运行得更快,但没有那么优雅。对于这个解决方案,我知道CONFIG=Z的唯一可能类型是“A”。(注意,下面可能有输入错误,因为我在另一台机器上运行XSLT,并在这里用模拟列名/值重新键入。)



XMLSpy给出了一个错误:变量不能在此表达式中使用:Row[key(“…”,concat(…),-->$table1 Ryan,您说过您使用XSLT 2.0,XSLT 2.0中允许使用该表达式(但我认为不是在1.0中)。因此,请确保您使用XSLT 2.0处理器。我尝试了使用Saxon 9.4和AltovaXML的完整样式表,它们按预期运行代码。对不起,我是XSLT新手。我发现了如何在XMLSpy中更改处理器,并且它起了作用。如果不是太难,您能为XSLT 1.0提供一个解决方案供将来参考吗?非常感谢。我将添加XSLT 1.0样式表,因为XSLT 1.0中没有将上下文文档作为第三个参数的
key
函数,并且在XSLT 1.0匹配模式中不允许使用变量。您必须将一些逻辑和上下文节点更改放入模板
match=“Row”
。谢谢..这在XSLT 1.0中非常适用,我发现它是我需要在目标系统上使用的版本。昨天我提出了一个“初学者”解决方案,它似乎比上面提供的解决方案运行得更快,但没有那么漂亮。我将它作为另一个答案发布。XMLSpy给出了一个错误:V