如何限制哪些节点在样式表中产生输出
我正在致力于转型。目标是将节点转换为键/值对。在这个论坛上找到了一个很棒的样式表推荐,但我可以使用一些帮助来对其进行一些调整。对于任何没有子节点的节点,节点名称应成为
的值,值应成为
的值。源文档可能有一些层次结构,但我想忽略它,只返回底部节点,当然是经过转换的。
这是我的源数据:
<?xml version="1.0" encoding="UTF-8"?>
<objects>
<Technical_Spec__c>
<Id>a0e30000000vFmbAAE</Id>
<F247__c>4.0</F247__c>
<F248__c xsi:nil="true"/>
<F273__c>Bronx</F273__c>
...
</Technical_Spec__c>
</objects>
这是样式表:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="*[count(*) = 0]">
<item>
<name>
<xsl:value-of select="name(.)" />
</name>
<value>
<xsl:value-of select="." />
</value>
</item>
</xsl:template>
<xsl:template match="*[count(*) > 0]">
<items>
<xsl:apply-templates/>
</items>
</xsl:template>
</xsl:stylesheet>
DESIRED OUTPUT - 样式表应该将这些节点转换为键值对,如下所示:
<items>
<item>
<name>F247__c</name>
<value>4.0</value>
</item>
<item>
<name>F248__c</name>
<value></value>
</item>
<item>
<name>F273__c</name>
<value>Bronx</value>
</item>
...
</items>
CURRENT OUTPUT - 但它创建了这样的嵌套“items”元素:
<items>
<items>
<item><name></name><value></value></item>
...
</items>
</items>
我理解(我认为)它是匹配所有父节点,包括顶部节点“objects”并嵌套“matches count 0”模板。因此,我尝试更改 matches 属性以排除“objects”并从“Technical_Spec__c”开始,如下所示(仅模板行):
<xsl:template match="objects/Technical_Spec__c/*">
<xsl:template match="*[count(*) = 0]">
<xsl:template match="objects/*[count(*) > 0]">
在我看来,这表示“第一个(主)模板仅与父级“objects/Tech_Spec”匹配的节点。第二个(内部)模板匹配任何没有子节点的节点。第三个(外部)模板匹配具有父“对象”的节点” - 这应该将我限制为一个。
更改匹配后的输出 - 这是我得到的结果:
<?xml version="1.0" encoding="UTF-8"?>
- <items xmlns=""><?xml version="1.0"?>
<item><name>Id</name><value>a0e30000000vFmbAAE</value></item>
<item><name>F247__c</name><value>4.0</value></item>
...
</items>
额外的
块消失了,但中间有一个额外的 块,因此它不再被识别为有效的 xml。
有什么想法吗?为什么要额外的 ;如何将模板限制为树的特定部分?
I am working on a transform. The goal is to transform nodes into key/value pairs. Found a great stylesheet recommendation on this forum but I could use some help to tweak it a bit. For any node that has no children, the node name should become the value of <name>
and the value should become the value of <value>
. The source document may have some hierarchical structure to it, but I want to ignore that and only return the bottom nodes, transformed of course.
Here is my source data:
<?xml version="1.0" encoding="UTF-8"?>
<objects>
<Technical_Spec__c>
<Id>a0e30000000vFmbAAE</Id>
<F247__c>4.0</F247__c>
<F248__c xsi:nil="true"/>
<F273__c>Bronx</F273__c>
...
</Technical_Spec__c>
</objects>
Here is the stylesheet:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="*[count(*) = 0]">
<item>
<name>
<xsl:value-of select="name(.)" />
</name>
<value>
<xsl:value-of select="." />
</value>
</item>
</xsl:template>
<xsl:template match="*[count(*) > 0]">
<items>
<xsl:apply-templates/>
</items>
</xsl:template>
</xsl:stylesheet>
DESIRED OUTPUT - The stylesheet should transform these nodes to key value pairs like this:
<items>
<item>
<name>F247__c</name>
<value>4.0</value>
</item>
<item>
<name>F248__c</name>
<value></value>
</item>
<item>
<name>F273__c</name>
<value>Bronx</value>
</item>
...
</items>
CURRENT OUTPUT - But it creates nested 'items' elements like this:
<items>
<items>
<item><name></name><value></value></item>
...
</items>
</items>
I understand (I think) that it is matching all the parent nodes including the top node 'objects' and nesting the 'matches count 0' template. So I tried altering the matches attribute to exclude 'objects' and start at 'Technical_Spec__c' like this (just the template lines):
<xsl:template match="objects/Technical_Spec__c/*">
<xsl:template match="*[count(*) = 0]">
<xsl:template match="objects/*[count(*) > 0]">
In my mind this says "First (master) template only matches nodes with parents 'objects/Tech_Spec'. Second (inner) template matches any node with no children. Third (outer) template matches nodes with parent 'objects' " - which should limit me to one .
OUTPUT AFTER ALTERING MATCH - Here is what I get:
<?xml version="1.0" encoding="UTF-8"?>
- <items xmlns=""><?xml version="1.0"?>
<item><name>Id</name><value>a0e30000000vFmbAAE</value></item>
<item><name>F247__c</name><value>4.0</value></item>
...
</items>
The extra <items>
block is gone but there is an extra <?xml>
block stuck in the middle so it's not recognized as valid xml anymore.
Any ideas? Why the extra <?xml>
; How to restrict template to particular parts of the tree?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
经过大量的试验和错误,我偶然发现了以下解决方案:我向第三个模板匹配条件添加了根锚点。
我现在有
/*[count(*) > 0],而不是
。这似乎消除了外部match="*[count(*) > 0]"
0]
元素。如果有人能告诉我原因,我将不胜感激。为什么这与/objects/*[count(*) > 不同? 0]
?我确实认为 Dimitre 关于处理器(IBM Cast Iron)的说法是正确的,所以我确实开了一张票。我在在线 XSLT 测试器上测试了上面相同的样式表,但没有获得额外的
标记。
Through a great deal of trial and error, I stumbled on the following solution: I added a root anchor to the third template match criteria.
Instead of
match="*[count(*) > 0]"
, I now have/*[count(*) > 0]
. This appears to eliminate the outer<items>
element. If anyone can tell me why, I'd appreciate it. Why would this be different than/objects/*[count(*) > 0]
?I do think Dimitre is right about the processor (which is IBM Cast Iron) so I did open a ticket. I tested the same stylesheet from above on an online XSLT tester and did not get the extra
<?xml ?>
tag.