问题描述
我正在研究具有不同输入 xml 文件的基于 Java 的 xsl 转换(XSLT 2.0,如果有免费的 Java 处理器,也可以是 XSLT 3.0).一个输入文件可能如下所示:
I'm working on a Java based xsl-transformation (XSLT 2.0, could also be XSLT 3.0 if there is a free processor for java) with different input xml files. one input file could look like this:
<?xml version="1.0" encoding="UTF-8"?>
<TEST>
<MyElement>
<CHILD>A</CHILD>
<CHILDBEZ>ABEZ</CHILDBEZ>
<NotInteresting></NotInteresting>
</MyElement>
<MyElement>
<CHILD>B</CHILD>
<CHILDBEZ>BBEZ</CHILDBEZ>
<NotInteresting2></NotInteresting2>
</MyElement>
</TEST>
我想复制除NotInteresting"以外的所有元素,并根据我从映射文件中获得的两个参数重命名两个节点 CHILD 和 CHILDBEZ:
I want to copy all elements but "NotInteresting" and rename the two nodes CHILD and CHILDBEZ based on two parameters that I get from a mapping file:
- 告诉我感兴趣的文本所在位置的 xpath 表达式(在本例中为:TEST/MyFirstElement/CHILD 和 TEST/MyFirstElement/CHILDBEZ)
- 以及它们在输出文件中应该包含的元素的名称(在本例中:childName 和 childBez)
映射文件:
<?xml version="1.0" encoding="UTF-8"?>
<element root="TEST">
<childName>TEST/MyElement/CHILD</childName>
<childBez>TEST/MyElement/CHILDBEZ</childBez>
</element>
所需的输出:
<TEST>
<MyElement>
<childName>A</childName>
<childBez>ABEZ</childBez>
</MyElement>
<MyElement>
<childName>B</childName>
<childBez>BBEZ</childBez>
</MyElement>
</TEST>
到目前为止我所拥有的:
what I have so far:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="2.0 "
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.apoverlag.at"
xmlns:apo="http://www.apoverlag.at">
<xsl:variable name="vars" select="document('mapping.xml')"/>
<xsl:param name="src" />
<xsl:variable name="path" xpath-default-namespace="" select="$src/path"/> <!-- = TEST/*-->
<xsl:template match="/">
<xsl:for-each select="$path">
<xsl:call-template name="buildNode">
<xsl:with-param name="currentNode" select="current()"></xsl:with-param>
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="buildNode">
<xsl:param name="currentNode" />
<xsl:element name="test">
<xsl:for-each select="$vars/element/@root">
<xsl:for-each select="$vars/element/*">
<xsl:element name="{name(.)}"> <xsl:value-of select="concat($currentNode,'/',current())" />
</xsl:element>
</xsl:for-each>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:transform>
我的问题是:
<xsl:value-of select="concat($currentNode,'/',current())" />
当我尝试硬编码时给我/TEST/MyFirstElement/CHILD":
gives me "/TEST/MyFirstElement/CHILD" when I try it hardcoded with:
<xsl:value-of select="$currentNode/CHILD" />
我收到了我想要的输出.谁能给我一个提示如何解决这个问题?
I receive my desired output. Can anyone give me a hint how to solve this problem?
推荐答案
我建议采用完全不同的方法.为简化起见,我使用了一个带有完整路径的映射文档(从 /
根节点开始):
I would suggest a radically different approach. To simplify, I have used a mapping document with full paths (starting with the /
root node):
映射xml
<element root="TEST">
<childName>/TEST/MyElement/CHILD</childName>
<childBez>/TEST/MyElement/CHILDBEZ</childBez>
</element>
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:param name="mapping" select="document('mapping.xml')"/>
<xsl:key name="map" match="*" use="." />
<xsl:template match="/">
<xsl:variable name="first-pass">
<xsl:apply-templates mode="first-pass"/>
</xsl:variable>
<xsl:apply-templates select="$first-pass/*"/>
</xsl:template>
<xsl:template match="*" mode="first-pass">
<xsl:param name="parent-path"/>
<xsl:variable name="path" select="concat($parent-path, '/', name())" />
<xsl:variable name="replacement" select="key('map', $path, $mapping)" />
<xsl:element name="{if ($replacement) then name($replacement) else name()}">
<xsl:attribute name="original" select="not($replacement)"/>
<xsl:apply-templates mode="first-pass">
<xsl:with-param name="parent-path" select="$path"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[@original='true' and not(descendant::*/@original='false')]"/>
</xsl:stylesheet>
结果,当应用于提供的输入时:
Result, when applied to the provided input:
<?xml version="1.0" encoding="UTF-8"?>
<TEST>
<MyElement>
<childName>A</childName>
<childBez>ABEZ</childBez>
</MyElement>
<MyElement>
<childName>B</childName>
<childBez>BBEZ</childBez>
</MyElement>
</TEST>
这篇关于带变量的 XSLT 2.0 XPATH 表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!