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>
备注:
您的前两个模板是多余的; 内置模板规则
已经这样做了;
你的测试<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>
我在 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>
备注:
您的前两个模板是多余的; 内置模板规则 已经这样做了;
你的测试
<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>