我有两个名为data1.xml和data2.xml的XML文件,使用XSLT我如何生成result.xml,在data2.xml中我使用selectValFrm
属性来指定XPATH来选择值表单。和其他属性一样。
data1.xml作为
<inputRoot>
<childOne>
I am first child
</childOne>
<childTwo>
<nestedChild id="1">
I am second child
</nestedChild>
</childTwo>
</inputRoot>
data2.xml
<result>
<ChildOneDesc selectValFrm="root/childOne"></ChildOneDesc>
<ChildTwoDesc>
<value num="root/childTwo/nestedChild/@id" selectValFrm="root/childTwo/nestedChild"></value>
</ChildTwoDesc>
</result>
为result.xml
<result>
<ChildOneDesc>
I am first child
</ChildOneDesc>
<ChildTwoDesc>
<value num="1">
I am second child
</value>
</ChildTwoDesc>
</result>
我写了一个XSLT,如:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:java="http://xml.apache.org/xslt/java"
xmlns:LocaTime="xalan://org.joda.time.LocalTime"
xmlns:LocaDate="xalan://org.joda.time.LocalDate">
<xsl:output method="xml" encoding="utf-8" indent="yes" />
<xsl:param name="xml-input" as="xs:string" />
<xsl:param name="xml-input-data" select="document($xml-input)" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*" name="init-element-value">
<xsl:element name="{name()}">
<xsl:value-of select="$xml-input-data/{@selectValFrm}"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*" name="init-attribute-value">
<xsl:attribute name="{name()}">
<xsl:value-of select="$xml-input-data/{how to resolve attribute value}"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
不工作,不知道如何实现这个结果?
答案 0 :(得分:2)
如果 - 看起来 - 你使用Xalan作为XSLT处理器,你可以使用EXSLT dyn:evaluate()
扩展函数来评估给定的字符串作为XPath表达式。试试例如:
XSLT 1.0 + EXSLT
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dyn="http://exslt.org/dynamic"
extension-element-prefixes="dyn">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="data-url" select="'data1.xml'"/>
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@selectValFrm">
<xsl:variable name="path" select="." />
<xsl:for-each select="document($data-url)">
<xsl:value-of select="dyn:evaluate($path)"/>
</xsl:for-each>
</xsl:template>
<xsl:template match="@*">
<xsl:attribute name="{name()}">
<xsl:variable name="path" select="." />
<xsl:for-each select="document($data-url)">
<xsl:value-of select="dyn:evaluate($path)"/>
</xsl:for-each>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
为了实际产生预期结果,您的输入文档(data2.xml)需要按照Martin Honnen的回答进行修改。
答案 1 :(得分:1)
如果您可以使用Saxon 9.7(也可能是9.6)PE或EE,那么您可以使用XSLT 3.0和xsl:evaluate
,这是一个例子:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="3.0">
<xsl:param name="xml-input" as="xs:string" select="'test201512150101.xml'"/>
<xsl:param name="xml-input-data" select="document($xml-input)" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[@selectValFrm]">
<xsl:copy>
<xsl:apply-templates select="@* except @selectValFrm"/>
<xsl:value-of>
<xsl:evaluate xpath="@selectValFrm" context-item="$xml-input-data"/>
</xsl:value-of>
</xsl:copy>
</xsl:template>
<xsl:template match="@num">
<xsl:attribute name="{name()}" namespace="{namespace-uri()}">
<xsl:evaluate xpath="." context-item="$xml-input-data"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
如果输入文件是
<result>
<ChildOneDesc selectValFrm="inputRoot/childOne"></ChildOneDesc>
<ChildTwoDesc>
<value num="inputRoot/childTwo/nestedChild/@id" selectValFrm="inputRoot/childTwo/nestedChild"></value>
</ChildTwoDesc>
</result>
(注意我必须将XPath值更改为以inputRoot
而不是root
开头),参数文档为
<inputRoot>
<childOne>
I am first child
</childOne>
<childTwo>
<nestedChild id="1">
I am second child
</nestedChild>
</childTwo>
</inputRoot>
然后结果是
<result>
<ChildOneDesc>
I am first child
</ChildOneDesc>
<ChildTwoDesc>
<value num="1">
I am second child
</value>
</ChildTwoDesc>
</result>
其他XSLT处理器可能提供扩展功能或指令来使用XPath评估,我们需要知道您使用的处理器,使用as="xs:string"
表示您使用的是XSLT 2.0处理器。