如何限制哪些节点在样式表中产生输出

发布于 2024-12-06 08:55:38 字数 2924 浏览 0 评论 0原文

我正在致力于转型。目标是将节点转换为键/值对。在这个论坛上找到了一个很棒的样式表推荐,但我可以使用一些帮助来对其进行一些调整。对于任何没有子节点的节点,节点名称应成为 的值,值应成为 的值。源文档可能有一些层次结构,但我想忽略它,只返回底部节点,当然是经过转换的。

这是我的源数据:

<?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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

烟凡古楼 2024-12-13 08:55:38

经过大量的试验和错误,我偶然发现了以下解决方案:我向第三个模板匹配条件添加了根锚点。

我现在有 /*[count(*) > 0],而不是 match="*[count(*) > 0]" 0]。这似乎消除了外部 元素。如果有人能告诉我原因,我将不胜感激。为什么这与 /objects/*[count(*) > 不同? 0]

我确实认为 Dimitre 关于处理器(IBM Cast Iron)的说法是正确的,所以我确实开了一张票。我在在线 XSLT 测试器上测试了上面相同的样式表,但没有获得额外的 标记。

<?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>

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.

<?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>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文