在这个代码示例中,我有两个挑战,一个是在B节点之后和节点C,D和E之前设置B1节点,第二个挑战是将第二个KEY节点添加到/ ROOT / E / OTHER / DEAL / KEYS结构。
此XML示例:
<ROOT>
<A>some A text</A>
<B>some B text</B>
<C>some C text</C>
<D>some D text</D>
<E>
<OTHER>
<DEAL>
<KEYS>
<KEY>
<KeyIdentifierType>KeyIdentifierTypeA</KeyIdentifierType>
<KeyValue>123456|1</KeyValue>
</KEY>
</KEYS>
</DEAL>
</OTHER>
</E>
</ROOT>
转型后:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Identifiers are added by the system. Need to pass parms from the calling program -->
<xsl:template match="ROOT" name="add-B1">
<xsl:variable name="elements-after" select="C|D|E"/>
<xsl:copy>
<xsl:copy-of select="* except $elements-after"/>
<B1>some B1 text</B1>
<xsl:copy-of select="$elements-after"/>
</xsl:copy>
</xsl:template>
<!-- KEY is added by the system. Need to pass parms from the calling program -->
<xsl:template match="ROOT/E/OTHER/DEAL/KEYS" name="add-KEYS">
<xsl:param name="KeyIdentifierTypeB">654321|1</xsl:param>
<xsl:copy>
<xsl:copy-of select="*"/>
<KEY>
<KeyIdentifierType>KeyIdentifierTypeB</KeyIdentifierType>
<KeyValue>
<xsl:value-of select="$KeyIdentifierTypeB"/>
</KeyValue>
</KEY>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
成为:
<?xml version="1.0" encoding="UTF-8"?>
<ROOT>
<A>some A text</A>
<B>some B text</B>
<B1 xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">some B1 text</B1>
<C>some C text</C>
<D>some D text</D>
<E>
<OTHER>
<DEAL>
<KEYS>
<KEY>
<KeyIdentifierType>KeyIdentifierTypeA</KeyIdentifierType>
<KeyValue>123456|1</KeyValue>
</KEY>
</KEYS>
</DEAL>
</OTHER>
</E>
</ROOT>
为什么第二个模板定义被完全忽略了?
第一个代码学院已经解决了B1节点在B节点之后和节点C,D和E之前设置,或者换句话说B1节点被设置,并且必须在其之后放置的节点是:C,D和E.
应满足第二个挑战部分的第二个模板匹配=“ROOT / E / OTHER / DEAL / KEYS”:将第二个KEY节点添加到/ ROOT / E / OTHER / DEAL / KEYS结构,已被完全忽略。
除了这个事实,如果你在ROOT节点上评论第一个模板匹配,第二个模板匹配=“ROOT / E / OTHER / DEAL / KEYS”将正常工作,它实际上会添加额外的密钥,但我不知道我知道为什么第一个模板匹配总是覆盖第二个模板匹配。我尝试xsl:template match =“ROOT / E / OTHER / DEAL / KEYS ...和xsl:for-each select = ...和xsl:call-template name =”add-KEYS“但没有任何帮助我进行。
我实际上理解,apply-templates,匹配具有更高优先级的更高结构的节点模板。更改XSLT文件中的模板位置不会产生任何影响,它不会按照确切的行序列读取它,而是通过匹配优先级来处理它。 每个匹配模板的“apply-templates”将对XML结构进行更改,隐含地它将为我们制作“for-each”,但我不知道如何“建议”结构已更改的第二个模板,以及为什么我应该这样做,因为第二个模板匹配正在寻找不同的XPath位置,从来没有从第一个模板触及btw。我应该在我的案例中应用模板排序吗?...以及最佳做法是什么?
预期结果:
<?xml version="1.0" encoding="UTF-8"?>
<ROOT>
<A>some A text</A>
<B>some B text</B>
<B1>some B1 text</B1>
<C>some C text</C>
<D>some D text</D>
<E>
<OTHER>
<DEAL>
<KEYS>
<KEY>
<KeyIdentifierType>KeyIdentifierTypeA</KeyIdentifierType>
<KeyValue>123456|1</KeyValue>
</KEY>
<KEY>
<KeyIdentifierType>KeyIdentifierTypeB</KeyIdentifierType>
<KeyValue>654321|1</KeyValue>
</KEY>
</KEYS>
</DEAL>
</OTHER>
</E>
</ROOT>
答案 0 :(得分:3)
应该的第二个模板
match="ROOT/E/OTHER/DEAL/KEYS"
满足第二个挑战部分:将第二个KEY节点添加到/ROOT/E/OTHER/DEAL/KEYS
结构已完全被忽略。
问题是在匹配ROOT
的模板中没有xsl:apply-templates
。仅选择模板以在xsl:apply-templates
指令的结果中执行。在您的代码中没有任何xsl:apply-templates
,因此XSLT处理器不再应用模板并完成执行。
如果您将xsl:copy-of
替换为xsl:apply-templates
,则会有所不同。
以下是如何执行此操作:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates select="@*|B/preceding-sibling::node()"/>
<xsl:apply-templates select="B"/>
<B1>some B1 text</B1>
<xsl:apply-templates select="B/following-sibling::node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="KEY">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<KEY>
<KeyIdentifierType>KeyIdentifierTypeB</KeyIdentifierType>
<KeyValue>
<xsl:value-of select="'654321|1'"/>
</KeyValue>
</KEY>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<ROOT>
<A>some A text</A>
<B>some B text</B>
<C>some C text</C>
<D>some D text</D>
<E>
<OTHER>
<DEAL>
<KEYS>
<KEY>
<KeyIdentifierType>KeyIdentifierTypeA</KeyIdentifierType>
<KeyValue>123456|1</KeyValue>
</KEY>
</KEYS>
</DEAL>
</OTHER>
</E>
</ROOT>
产生了想要的正确结果:
<ROOT>
<A>some A text</A>
<B>some B text</B>
<B1>some B1 text</B1>
<C>some C text</C>
<D>some D text</D>
<E>
<OTHER>
<DEAL>
<KEYS>
<KEY>
<KeyIdentifierType>KeyIdentifierTypeA</KeyIdentifierType>
<KeyValue>123456|1</KeyValue>
<KEY>
<KeyIdentifierType>KeyIdentifierTypeB</KeyIdentifierType>
<KeyValue>654321|1</KeyValue>
</KEY>
</KEY>
</KEYS>
</DEAL>
</OTHER>
</E>
</ROOT>