XSLT 2.0 在 for-each 中使用 xsl copy/copy-of,覆盖某些属性

XSLT 2.0 using xsl copy/copy-of in for-each, overwriting certain attributes

我在 for-each 循环中复制节点和覆盖元素时遇到麻烦。

代码:

        <xsl:for-each select="key('doc_checks', @id, $doc_checks_File)">
            <xsl:if test="@id = $curID">
                <xsl:copy-of select="."/>
            </xsl:if>
        </xsl:for-each>

复制所有内容,这很好,但我需要覆盖两个属性(或者更确切地说,不应将它们复制到结果文档中)。

传递给关键函数的文件看起来像这样:

<doc id="1eb79a4952644db089fd7eb049bb5b58" fileNameInDB="d041397121636931.xml" version="1">
        <docref id="ec699e0817fb46a0817b0fa276a249f8" fileNameInDB="d041385554715361.xml" href="ec699e0817fb46a0817b0fa276a249f8.xml" version="1">
            <docref id="91f233476f4d1014b6dd926db0e91070" fileNameInDB="d041385557506665.xml" href="91f233476f4d1014b6dd926db0e91070.xml" navtitle="Model View Controller (MVC) Approach"version="1">
                <docref id="e1b625940c104b558e52f47afe5ddb4f" fileNameInDB="c511393250787627.xml" href="e1b625940c104b558e52f47afe5ddb4f.xml" version="1"/>
                </docref>
        </docref>
</doc>

我在输出中需要相同的结构,但没有 fileNameInDB 属性。

编辑

<xsl:stylesheet>

<xsl:key name="doc_checks" match="doc" use="@id"/>
<xsl:param name="doc_checks_File" select="fn:doc(fn:iri-to-uri('doc_checks.xml'))"/>

<xsl:template match="/">
<xsl:apply-templates>
</xsl:template>

<xsl:template match="docs">
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="doc">

<xsl:variable name="curID" select="@id"/>

<xsl:for-each select="key('doc_checks', @id, $doc_checks_File)">
    <xsl:if test="@id = $curID">
        <!-- copy structure from $doc_checks_File -->
    </xsl:if>
</xsl:for-each>


</xsl:templates>

</xsl:stylesheet>

输入:

<docs>
<doc id="1eb79a4952644db089fd7eb049bb5b58"/>
<doc id="2379a4952563db089fd7e2dz049bb648"/>
<!-- and so on -->
</docs>

参考文档doc_checks.xml(关键功能):

<doc_checks>
    <doc id="1eb79a4952644db089fd7eb049bb5b58" fileNameInDB="d041397121636931.xml" version="1">
            <docref id="ec699e0817fb46a0817b0fa276a249f8" fileNameInDB="d041385554715361.xml" href="ec699e0817fb46a0817b0fa276a249f8.xml" version="1">
                <docref id="91f233476f4d1014b6dd926db0e91070" fileNameInDB="d041385557506665.xml" href="91f233476f4d1014b6dd926db0e91070.xml" navtitle="Model View Controller (MVC) Approach"version="1">
                    <docref id="e1b625940c104b558e52f47afe5ddb4f" fileNameInDB="c511393250787627.xml" href="e1b625940c104b558e52f47afe5ddb4f.xml" version="1"/>
                    </docref>
            </docref>
    </doc>

<doc id="2379a4952563db089fd7e2dz049bb648">
<!-- a couple of docrefs, like above -->
</doc>

预期输出(<new> 无关)

<new>
<doc id="1eb79a4952644db089fd7eb049bb5b58">
<docref id="ec699e0817fb46a0817b0fa276a249f8" href="ec699e0817fb46a0817b0fa276a249f8.xml" version="1">
                <docref id="91f233476f4d1014b6dd926db0e91070" href="91f233476f4d1014b6dd926db0e91070.xml" navtitle="Model View Controller (MVC) Approach"version="1">
                    <docref id="e1b625940c104b558e52f47afe5ddb4f"  href="e1b625940c104b558e52f47afe5ddb4f.xml" version="1"/>
                    </docref>
            </docref>
</doc>

<doc id="2379a4952563db089fd7e2dz049bb648">
<!-- the respective docref elements from doc_checks.xml -->
</doc>
</new>

xsl:copy-of 复制选中的节点及其整个后代树,没有选择的可能。试试像这样的东西:

<xsl:apply-templates select="key('doc_checks', @id, $doc_checks_File)[@id = $curID]"/>

然后用这两个模板来处理调用:

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

<xsl:template match="@fileNameInDB"/>

警告:你没有post一个可重现的例子,所以这可能需要一些改变才能在你的场景中工作。


编辑:

鉴于您添加的代码,这里是在完整样式表上下文中的建议方法:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="doc_checks" match="doc" use="@id"/>
<xsl:param name="doc_checks_File" select="document('doc_checks.xml')"/>

<xsl:template match="/docs">
    <new>
        <xsl:for-each select="doc">
            <xsl:apply-templates select="key('doc_checks', @id, $doc_checks_File)"/>
        </xsl:for-each>
    </new>
</xsl:template>

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

<xsl:template match="@fileNameInDB"/>

</xsl:stylesheet>

应用于您的输入示例(在更正 doc_checks.xml 文档的格式正确之后!!),结果是:

<?xml version="1.0" encoding="UTF-8"?>
<new>
   <doc id="1eb79a4952644db089fd7eb049bb5b58" version="1">
      <docref id="ec699e0817fb46a0817b0fa276a249f8"
              href="ec699e0817fb46a0817b0fa276a249f8.xml"
              version="1">
         <docref id="91f233476f4d1014b6dd926db0e91070"
                 href="91f233476f4d1014b6dd926db0e91070.xml"
                 navtitle="Model View Controller (MVC) Approach"
                 version="1">
            <docref id="e1b625940c104b558e52f47afe5ddb4f"
                    href="e1b625940c104b558e52f47afe5ddb4f.xml"
                    version="1"/>
         </docref>
      </docref>
   </doc>
   <doc id="2379a4952563db089fd7e2dz049bb648"><!-- a couple of docrefs, like above --></doc>
</new>

备注:

  1. 您的前两个模板是多余的; 内置模板规则 已经这样做了;

  2. 你的测试<xsl:if test="@id = $curID">是多余的; key 已经解决了这个问题。

这对我有用:

<xsl:template match="someElement">
    <xsl:for-each select="key('keyname', concat(@id, '+', @folder), $reuseFile)/child::*">
        <xsl:copy>
<!-- overwrite attribute -->
            <xsl:attribute name="rev" select="@ver"/>
<!-- exclude certain attributes -->
                <xsl:copy-of select="@*[fn:local-name() != 'somename']"/>
            <xsl:apply-templates select="node()"/> <!-- chooses the template below -->
        </xsl:copy>
    </xsl:for-each>
</xsl:template>

<xsl:template match="abc | def">
    <xsl:copy>
        <xsl:attribute name="rev" select="@ver"/>
        <xsl:copy-of select="@*[fn:local-name() != 'somename']"/>
        <xsl:apply-templates select="node()"/>
    </xsl:copy>
</xsl:template>