我试图使用xslt来执行简单的地图。
首先,我定义一个指向我要复制的节点的变量,然后使用" xsl:copy-of select = $ var"
Ex. <xsl:variable name="myVar1" select="//cds/cd[@name='2']/node1/node2/addr2" />
这对于简单的测试xsl和test xml工作正常。但是对于实际的xml,它根本就不是复制节点。
测试xsl和实际的xsl之间的区别仅在于实际xsl中的节点名称实际上很长(需要应用它的xml具有长节点名称),并且测试xsl&amp; xml没有任何名称空间前缀。
如果我将变量仅指向根节点即<xsl:variable name="myVar1" select="//cds/cd[@name='2']
,但我想将节点复制到该节点之下(即node1 / node2 / addr2)
我没有在xsl中看到任何错误(我使用XMLSpy),只是想知道在定义变量时是否对节点名称的长度有任何限制?
谢谢, 阿希什
只是弄清楚导致问题的原因但不确定如何修复。是的,这些问题似乎与命名空间有关。当我在下面的示例xml中添加命名空间&#34; a&#34; 时,它停止工作(真正的xml有这样的命名空间)。
输入XML
<store>
<cds>
<cd name="0">
<test>this is test 0</test>
</cd>
<cd name="1">
<node1 xmlns="anothernamespace">
<node2 xmlns:a="http://someurl.com/something">
<addr1>
<country>country1</country>
</addr1>
<addr2>
<state>state1</state>
</addr2>
<a:addr3>
<city>city1</city>
<phone>123</phone>
<email>email1</email>
<website xmlns:b="somenamespace">
<b:name>website name</b:name>
<a:category>blog</a:category>
</website>
</a:addr3>
</node2>
</node1>
</cd>
<cd name="2">
<test>this is test2</test>
</cd>
</cds>
</store>
XSLT代码
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
<xsl:template match="/">
<xsl:variable name="myVar1" select="//cds/cd[@name='1']/node1/node2/addr3" />
<addr>
<xsl:copy-of select="$myVar1" />
</addr>
</xsl:template>
</xsl:stylesheet>
如果xml没有名称空间&#34; a&#34;
,这样可以正常工作答案 0 :(得分:2)
首先,您需要在样式表中声明命名空间,为其分配前缀,并在寻址该命名空间中的节点时使用该前缀。
另一件事是,复制节点时,还要复制其命名空间。你没有发布你的预期结果,但我认为这不是你想要的。
另请注意,当您将节点(示例中为a:addr3
)复制到另一个节点(addr
)时,您将最终获得整个节点,包括启动和结束标记,嵌套在目标节点内。同样,我认为这不是你想要的。
尝试以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:a="http://someurl.com/something"
exclude-result-prefixes="a">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:variable name="myVar1" select="//cds/cd[@name='1']/node1/node2/a:addr3" />
<addr>
<xsl:apply-templates select="$myVar1/*" mode="remove-ns"/>
</addr>
</xsl:template>
<xsl:template match="*" mode="remove-ns">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="*" mode="remove-ns"/>
<xsl:apply-templates select="@*|text()"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
当应用于您的(相当奇怪的)示例输入时:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Edited by XMLSpy -->
<store>
<cds>
<cd name="0">
<test>this is test 0</test>
</cd>
<cd name="1">
<node1>
<node2 xmlns:a="http://someurl.com/something">
<addr1>
<country>country1</country>
</addr1>
<addr2>
<state>state1</state>
</addr2>
<a:addr3>
<city>city1</city>
<phone>123</phone>
<email>email1</email>
<website>
<name>website name</name>
</website>
</a:addr3>
</node2>
</node1>
</cd>
<cd name="2">
<test>this is test2</test>
</cd>
</cds>
</store>
结果将是:
<addr>
<city>city1</city>
<phone>123</phone>
<email>email1</email>
<website>
<name>website name</name>
</website>
</addr>
关于您的更新输入:
<store>
<cds>
<cd name="0">
<test>this is test 0</test>
</cd>
<cd name="1">
<node1 xmlns="anothernamespace">
<node2 xmlns:a="http://someurl.com/something">
<addr1>
<country>country1</country>
</addr1>
<addr2>
<state>state1</state>
</addr2>
<a:addr3>
<city>city1</city>
<phone>123</phone>
<email>email1</email>
<website xmlns:b="somenamespace">
<b:name>website name</b:name>
<a:category>blog</a:category>
</website>
</a:addr3>
</node2>
</node1>
</cd>
<cd name="2">
<test>this is test2</test>
</cd>
</cds>
</store>
这里的问题是节点继承其父节点的名称空间(除非它们被显式放入另一个名称空间)。在这里,您不仅需要考虑a:addr3
的命名空间,还需要考虑a:addr3
的祖先所有节点的命名空间:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ans="anothernamespace"
xmlns:a="http://someurl.com/something"
exclude-result-prefixes="ans a">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:variable name="myVar1" select="//cds/cd[@name='1']/ans:node1/ans:node2/a:addr3" />
<addr>
<xsl:apply-templates select="$myVar1/*" mode="remove-ns"/>
</addr>
</xsl:template>
<xsl:template match="*" mode="remove-ns">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="*" mode="remove-ns"/>
<xsl:apply-templates select="@*|text()"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
请注意,模板本身没有变化 - 只更改了样式表命名空间声明和存储在$myVar1
变量中的XPath。
答案 1 :(得分:1)
您需要在xslt的顶部定义'a'命名空间,然后在变量select中使用'a'添加前缀'addr3'。 它看起来如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:a="http://someurl.com/something">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
<xsl:template match="/">
<xsl:variable name="myVar1" select="//cds/cd[@name='1']/node1/node2/a:addr3" />
<addr>
<xsl:copy-of select="$myVar1" />
</addr>
</xsl:template>
</xsl:stylesheet>