gpt4 book ai didi

java - 如何通过参数在 XSLT 中设置命名空间名称

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

我需要在运行时在 XSLT 样式表中设置命名空间。这是我的 XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tdns="{$myNS}">
<xsl:output method="xml" encoding="iso-8859-1" />

<xsl:param name="myNS" required="yes" />

<xsl:template match="*">

<xsl:choose>
<xsl:when test="name(.)='bugs'">
<xsl:element name="tdns:bugs">

<xsl:for-each select="*">
<xsl:apply-templates select="." />
</xsl:for-each>
</xsl:element>
</xsl:when>
<xsl:when test="name(.)='bug'">

<xsl:element name="tdns:bug">
<xsl:for-each select="*">
<xsl:choose>
<xsl:when test="name(.)='Device' ">
<xsl:choose>
<xsl:when test="string-length(../tdns:Device_Tmp) &gt; 0 ">
<xsl:element name="tdns:Device">

<xsl:value-of select="../tdns:Device_Tmp" />
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:element name="tdns:Device">
<xsl:value-of select="." />
</xsl:element>
</xsl:otherwise>
</xsl:choose>
<xsl:element name="tdns:ShowParamValue">
<xsl:value-of select="$myNS" />
</xsl:element>
</xsl:when>

</xsl:choose>
</xsl:for-each>
</xsl:element>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

输入 XML

<?xml version="1.0" encoding="ISO-8859-1"?>
<bugs xmlns="http://my.com">
<bug>
<Device>
<![CDATA[Dev1]]>
</Device>
<Device_Tmp>
<![CDATA[Dev_tmp1]]>
</Device_Tmp>
</bug>
</bugs>

Java代码

TransformerFactory tfactory = TransformerFactory.newInstance();
Transformer transformer = tfactory.newTransformer(new StreamSource(
new File(xsl)));
transformer.setParameter("myNS", "http://my.com");
transformer.transform(new StreamSource(new File(
xml)),
new StreamResult(System.out));

输出 XML

<?xml version="1.0" encoding="iso-8859-1"?>
<tdns:bugs xmlns:tdns="http://my.com">
<tdns:bug>
<tdns:Device>
Dev1
</tdns:Device>
<tdns:ShowParamValue>http://my.com</tdns:ShowParamValue>
</tdns:bug>
</tdns:bugs>

如您所见,XSLT 不知道任何 ../tdns:Device_Tmp 节点,但是如果我设置静态命名空间:

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tdns="http://my.com">
...

那么,结果就OK了:

<?xml version="1.0" encoding="iso-8859-1"?>
<tdns:bugs xmlns:tdns="http://my.com">
<tdns:bug>
<tdns:Device>
Dev_tmp1
</tdns:Device>
<tdns:ShowParamValue>http://my.com</tdns:ShowParamValue>
</tdns:bug>
</tdns:bugs>

请告诉我我做错了什么。

最佳答案

命名空间声明不是属性,也不会被视为属性值模板(实际上,在它接近 XSLT 处理器之前,它们由解析样式表文档的 XML 解析器处理)。

你必须使用 <xsl:element>使用 name 创建元素和 namespace属性,以便能够动态指定命名空间。为了匹配元素,最简单的方法可能是完全忽略命名空间(因为您在 XSLT 2.0 中,这很容易使用 *:localname )。

<?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" encoding="iso-8859-1" />

<xsl:param name="myNS" required="yes" />

<!-- this will cover most things, including a Device that doesn't have a
sibling Device_Tmp -->
<xsl:template match="*">
<xsl:element name="tdns:{local-name()}" namespace="{$myNS}">
<xsl:apply-templates />
</xsl:element>
</xsl:template>

<!-- delete Device_Tmp -->
<xsl:template match="*:Device_Tmp" />

<!-- special case for Device elements that have a non-empty sibling
Device_Tmp -->
<xsl:template match="*:Device[string-length(../*:Device_Tmp) > 0]"
priority="2">
<xsl:element name="tdns:{local-name()}" namespace="{$myNS}">
<xsl:value-of select="../*:Device_Tmp" />
</xsl:element>
</xsl:template>

<!-- add debugging element to bug -->
<xsl:template match="*:bug">
<xsl:element name="tdns:{local-name()}" namespace="{$myNS}">
<xsl:apply-templates />
<xsl:element name="tdns:ShowParamValue" namespace="{$myNS}">
<xsl:value-of select="$myNS" />
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

关于java - 如何通过参数在 XSLT 中设置命名空间名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20564066/

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