gpt4 book ai didi

XSLT 2.0 - 将节点集作为参数传递似乎不起作用

转载 作者:行者123 更新时间:2023-12-01 11:35:30 25 4
gpt4 key购买 nike

我有一个文档需要转换,以便大多数元素按原样复制,但有一些异常(exception):对于某些指定的节点,需要附加子元素,并且其中一些子元素需要引用回特定的源文档中的元素。一个单独的“模型/人行横道”xml 文件包含要添加的元素。 crosswalk 中需要引用源文档的元素具有将它们指向特定元素的“源”属性。当然,我的实际源文档(以及实际的人行横道)比这些示例更加复杂和多样。

这是一个源文档示例:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<album>
<artist>Frank Sinatra</artist>
<title>Greatest Hits</title>
</album>
<album>
<artist>Miles Davis</artist>
<title>Kind Of Blue</title>
</album>
<movie>
<title>ET</title>
<director>Steven Spielberg</director>
</movie>
<movie>
<title>Blues Brothers</title>
<director>John Landis</director>
</movie>
</root>

这里是“人行横道”(crswlk.xml):

<?xml version="1.0" encoding="UTF-8"?>

<root>
<album>
<artist-info>
<artist2 source="artist"/>
</artist-info>
</album>
<movie>
<director-info>
<director2 source="director"/>
</director-info>
</movie>
</root>

这是期望的输出:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<album>
<artist>Frank Sinatra</artist>
<title>Greatest Hits</title>
<artist-info>
<artist2>Frank Sinatra</artist2>
</artist-info>
</album>
<album>
<artist>Miles Davis</artist>
<title>Kind Of Blue</title>
<artist-info>
<artist2>Miles Davis</artist2>
</artist-info>
</album>
<movie>
<title>ET</title>
<director>Steven Spielberg</director>
<director-info>
<director2>Steven Spielberg</director2>
</director-info>
</movie>
<movie>
<title>Blues Brothers</title>
<director>John Landis</director>
<director-info>
<director2>John Landis</director2>
</director-info>
</movie>
</root>

这是我的 xslt:

<?xml version="1.0" encoding="UTF-8"?>
<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:variable name="crosswalk" select="document('crswlk.xml')"/>

<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="*/album|movie">
<xsl:variable name="theNode" select="."/>
<xsl:variable name="nodeName" select="name()"/>
<xsl:element name="{$nodeName}">
<xsl:apply-templates select="@* | node()"/>
<xsl:apply-templates select="$crosswalk//*[name()=$nodeName]/*">
<xsl:with-param name="curNode" select="$theNode"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>

<xsl:template match="*[@source]">
<xsl:param name="curNode" />
<xsl:variable name="sourceNodeName" select="@source"/>
<xsl:element name="{name()}">
<xsl:value-of select="$curNode//*[name()=$sourceNodeName]"/>
</xsl:element>
</xsl:template>

</xsl:stylesheet>

一旦最后一个模板第一次尝试访问 $curNode 就会停止处理。当我在 Eclipse (Xalan 2.7.1) 中运行 xslt 时,它会抛出此错误:“java.lang.ClassCastException: org.apache.xpath.objects.XString cannot be cast to org.apache.xpath.objects.XNodeSet”。

如果我将一个类似的节点集作为参数传递给与源文档中的节点相匹配的模板,它会按预期工作——节点集是可访问的。但是,将节点集传递给上面最后一个模板是行不通的。是因为模板与外部文档中的节点相匹配吗?我当然不知道。非常感谢任何帮助,我花了一段时间才达到这一点。谢谢!

最佳答案

看起来你需要改变两件事:

  • tunnel="yes" 添加到 xsl:with-paramxsl:param
  • xsl:value-of 的谓词中的 '$sourceNodeName' 中删除撇号

更新的 XSLT:

<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:variable name="crosswalk" select="document('crswlk.xml')"/>

<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="*/album|movie">
<xsl:variable name="theNode" select="."/>
<xsl:variable name="nodeName" select="name()"/>
<xsl:element name="{$nodeName}">
<xsl:apply-templates select="@* | node()"/>
<xsl:apply-templates select="$crosswalk//*[name()=$nodeName]/*">
<xsl:with-param name="curNode" select="$theNode" tunnel="yes"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>

<xsl:template match="*[@source]">
<xsl:param name="curNode" tunnel="yes"/>
<xsl:variable name="sourceNodeName" select="@source"/>
<xsl:element name="{name()}">
<xsl:value-of select="$curNode//*[name()=$sourceNodeName]"/>
</xsl:element>
</xsl:template>

</xsl:stylesheet>

此外,您还可以删除一些额外的 xsl:variables...

<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:variable name="crosswalk" select="document('crswlk.xml')"/>

<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="album|movie">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<xsl:apply-templates select="$crosswalk/*/*[name()=current()/name()]/*">
<xsl:with-param name="curNode" select="." tunnel="yes"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>

<xsl:template match="*[@source]">
<xsl:param name="curNode" tunnel="yes"/>
<xsl:copy>
<xsl:value-of select="$curNode//*[name()=current()/@source]"/>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>

关于XSLT 2.0 - 将节点集作为参数传递似乎不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17624274/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com