我有以下输入。
XML输入
<DOC>
<ID>1234</ID>
<TXT>
<A><DESC type="PERSON">George Washington</DESC> lived in a house called <DESC type="PLACE">Mount Vernon.</DESC></A>
</TXT>
</DOC>
然后我应用以下XSLT
XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<DOC>
<xsl:for-each select="DOC/*">
<xsl:copy>
<xsl:value-of select="current()"/>
</xsl:copy>
</xsl:for-each>
<xsl:apply-templates select="DOC/TXT"/>
</DOC>
</xsl:template>
<xsl:template match="TXT">
<xsl:element name="TXT">
<xsl:for-each select="S">
<xsl:element name="{local-name()}">
<xsl:for-each select="*">
<xsl:variable name="type" select="@type"/>
<xsl:element name="{concat(name(), '_', $type)}">
<xsl:value-of select="current()"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
由此产生此输出。
输出
<DOC>
<ID>1234</ID>
<TXT>
George Washington lived in a house called Mount Vernon.
</TXT>
<TXT>
<A>
<DESC_PERSON>George Washington</DESC_PERSON>
<DESC_PLACE>Mount Vernon</DESC>
</A>
</TXT>
</DOC>
这几乎正是我想要的,但是,我需要将第一个TXT标签重命名为RAW_TXT,因为稍后我需要在NiFi中使用Avro架构,并且当该架构具有重复标签时会引发错误。我试图将下面的代码添加到XSLT中,但是它只是创建两个相同的raw_txt字段,并删除了DESC_PERSON
和DESC_PLACE
。
尝试
<xsl:template match="TXT">
<RAW_TXT><xsl:apply-templates select="@*|node()" /></RAW_TXT>
</xsl:template>
答案 0 :(得分:0)
如果您有两个与TXT
匹配的模板,那么这将被视为XSLT中的错误。有些处理器会标记错误,而其他处理器只会使用最后一个匹配的模板。
要区分它们,可以使用“模式”。您还需要将现有的xsl:copy
更改为xsl:apply-templates
,以允许使用非模式模板。
尝试使用此XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<DOC>
<xsl:apply-templates select="DOC/*" />
<xsl:apply-templates select="DOC/TXT" mode="extra"/>
</DOC>
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:value-of select="current()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="TXT">
<RAW_TXT>
<xsl:value-of select="current()"/>
</RAW_TXT>
</xsl:template>
<xsl:template match="TXT" mode="extra">
<TXT>
<xsl:for-each select="*">
<xsl:element name="{local-name()}">
<xsl:for-each select="*">
<xsl:variable name="type" select="@type"/>
<xsl:element name="{concat(name(), '_', $type)}">
<xsl:value-of select="current()"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</TXT>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
首先,您希望两个模板具有相同的模式(每个TXT
元素)。这是modes的用例,因为@Tim C回答了。
第二,您要处理所有内容(甚至是TXT
元素),然后重新处理TXT
元素以去除标记。这是named templated作为身份转换以及在任何模式中使用built-in rules的很好用例。
您的输入与此样式表:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="@*|node()" name="copy">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="TXT">
<xsl:call-template name="copy"/>
<RAW_TXT>
<xsl:apply-templates mode="text"/>
</RAW_TXT>
</xsl:template>
</xsl:stylesheet>
结果:
<DOC>
<ID>1234</ID>
<TXT>
<A>
<DESC type="PERSON">George Washington</DESC> lived in a house called <DESC type="PLACE">Mount Vernon.</DESC>
</A>
</TXT>
<RAW_TXT>George Washington lived in a house called Mount Vernon.</RAW_TXT>
</DOC>