如何通过匹配 XSLT 中的节点来复制值
How to copy values by matching nodes in XSLT
在我的 XML 中,如果两个节点在其他一些节点中具有匹配值,我想将值从另一个节点复制到一个节点。
<XML>
<ORG>
<ITM>
<NUM>1</NUM>
<SEQ>10</SEQ>
<VAL>X</VAL>
</ITM>
<ITM>
<NUM>2</NUM>
<SEQ>20</SEQ>
<VAL>Y</VAL>
</ITM>
</ORG>
<NEW>
<ITM>
<NUM>1</NUM>
<SEQ>10</SEQ>
<VAL>QQQ</VAL>
</ITM>
</NEW>
</XML>
这可行,但对于大型文档可能会很慢,有没有更好的方法?
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ORG/ITM/VAL">
<xsl:variable name="NUM" select="../NUM"/>
<xsl:variable name="SEQ" select="../SEQ"/>
<VAL>
<xsl:value-of select="../../../NEW/ITM/VAL[../NUM=$NUM and ../SEQ=$SEQ]"/>
</VAL>
</xsl:template>
</xsl:stylesheet>
结果在 ORG/ITM/VAL 节点中的值为 "QQQ",因为 ORG/ITM/NUM 和 ORD/ITM/SEQ 与 NEW/ITM/NUM 和 NEW/ITM/SEQ
<?xml version="1.0"?>
<XML>
<ORG>
<ITM>
<NUM>1</NUM>
<SEQ>10</SEQ>
<VAL>QQQ</VAL>
</ITM>
<ITM>
<NUM>2</NUM>
<SEQ>20</SEQ>
<VAL/>
</ITM>
</ORG>
<NEW>
<ITM>
<NUM>1</NUM>
<SEQ>10</SEQ>
<VAL>QQQ</VAL>
</ITM>
</NEW>
</XML>
使用 1 个变量更快。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ORG/ITM/VAL">
<xsl:variable name="NUMSEQ" select="concat(string(../NUM), string(../SEQ))"/>
<VAL>
<xsl:value-of select="../../../NEW/ITM/VAL[concat(string(../NUM), string(../SEQ))=$NUMSEQ]"/>
</VAL>
</xsl:template>
</xsl:stylesheet>
查找值的首选方法是定义 key 并使用它。在给定的示例中,这可能是:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="new-item" match="NEW/ITM" use="concat(NUM, '|', SEQ)" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ORG/ITM/VAL">
<xsl:copy>
<xsl:value-of select="key('new-item', concat(../NUM, '|', ../SEQ))/VAL"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
在我的 XML 中,如果两个节点在其他一些节点中具有匹配值,我想将值从另一个节点复制到一个节点。
<XML>
<ORG>
<ITM>
<NUM>1</NUM>
<SEQ>10</SEQ>
<VAL>X</VAL>
</ITM>
<ITM>
<NUM>2</NUM>
<SEQ>20</SEQ>
<VAL>Y</VAL>
</ITM>
</ORG>
<NEW>
<ITM>
<NUM>1</NUM>
<SEQ>10</SEQ>
<VAL>QQQ</VAL>
</ITM>
</NEW>
</XML>
这可行,但对于大型文档可能会很慢,有没有更好的方法?
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ORG/ITM/VAL">
<xsl:variable name="NUM" select="../NUM"/>
<xsl:variable name="SEQ" select="../SEQ"/>
<VAL>
<xsl:value-of select="../../../NEW/ITM/VAL[../NUM=$NUM and ../SEQ=$SEQ]"/>
</VAL>
</xsl:template>
</xsl:stylesheet>
结果在 ORG/ITM/VAL 节点中的值为 "QQQ",因为 ORG/ITM/NUM 和 ORD/ITM/SEQ 与 NEW/ITM/NUM 和 NEW/ITM/SEQ
<?xml version="1.0"?>
<XML>
<ORG>
<ITM>
<NUM>1</NUM>
<SEQ>10</SEQ>
<VAL>QQQ</VAL>
</ITM>
<ITM>
<NUM>2</NUM>
<SEQ>20</SEQ>
<VAL/>
</ITM>
</ORG>
<NEW>
<ITM>
<NUM>1</NUM>
<SEQ>10</SEQ>
<VAL>QQQ</VAL>
</ITM>
</NEW>
</XML>
使用 1 个变量更快。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ORG/ITM/VAL">
<xsl:variable name="NUMSEQ" select="concat(string(../NUM), string(../SEQ))"/>
<VAL>
<xsl:value-of select="../../../NEW/ITM/VAL[concat(string(../NUM), string(../SEQ))=$NUMSEQ]"/>
</VAL>
</xsl:template>
</xsl:stylesheet>
查找值的首选方法是定义 key 并使用它。在给定的示例中,这可能是:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="new-item" match="NEW/ITM" use="concat(NUM, '|', SEQ)" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ORG/ITM/VAL">
<xsl:copy>
<xsl:value-of select="key('new-item', concat(../NUM, '|', ../SEQ))/VAL"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>