XSL 匹配部分但不是全部

发布于 2024-10-23 23:38:08 字数 2122 浏览 1 评论 0原文

我从 之前的帖子中得到了一个解决方案,该解决方案由 迪米特雷·诺瓦切夫

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="my:my">
  <xsl:output method="xml" version="1.0" encoding="iso-8859-1" indent="yes"/>
  <xsl:key name="kPhysByName" match="KB_XMod_Modules" use="Physician"/>
  <xsl:template match="/">
    <result>
      <xsl:apply-templates/>
    </result>
  </xsl:template>
  <xsl:template match="/*/*/*[starts-with(name(), 'InfBy')]">
    <xsl:variable name="vCur" select="."/>
    <xsl:for-each select="document('doc2.xml')">
      <xsl:variable name="vMod" select="key('kPhysByName', $vCur)"/>
      <xsl:copy>
        <items>
          <item>
            <label>
              <xsl:value-of select="$vMod/Physician"/>
            </label>
            <value>
              <xsl:value-of select="$vMod/XModID"/>
            </value>
          </item>
        </items>
      </xsl:copy>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

我现在需要在源 XML 中使用其他字段,并且需要完整地保留现有标签,但我在执行此操作时遇到了问题。

<instance>
  <NewTag>Hello</newTag1>
  <AnotherNewTag>Everyone</AnotherNewTag>
  <InfBy1>Dr Phibes</InfBy1>
  <InfBy2>Dr X</InfBy2>
  <InfBy3>Dr Chivago</InfBy3>
</instance>

额外标签和输出,

<result xmlns:my="my:my">
  HelloEveryone 
  <items>
    <item>
      <label>Dr Phibes</label>
      <value>60</value>
    </item>
  </items>
  ...

它删除了我一直在尝试的

<xsl:otherwise>
  <xsl:copy-of select=".">
  </xsl:copy-of>
</xsl:otherwise>

但作为一个 xsl 新手,我似乎无法让它发挥作用。我有一种感觉,我找错了树!

有人有什么想法吗?

谢谢,

威尔

I have a solution from an earlier post that was kindly provided by Dimitre Novatchev.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="my:my">
  <xsl:output method="xml" version="1.0" encoding="iso-8859-1" indent="yes"/>
  <xsl:key name="kPhysByName" match="KB_XMod_Modules" use="Physician"/>
  <xsl:template match="/">
    <result>
      <xsl:apply-templates/>
    </result>
  </xsl:template>
  <xsl:template match="/*/*/*[starts-with(name(), 'InfBy')]">
    <xsl:variable name="vCur" select="."/>
    <xsl:for-each select="document('doc2.xml')">
      <xsl:variable name="vMod" select="key('kPhysByName', $vCur)"/>
      <xsl:copy>
        <items>
          <item>
            <label>
              <xsl:value-of select="$vMod/Physician"/>
            </label>
            <value>
              <xsl:value-of select="$vMod/XModID"/>
            </value>
          </item>
        </items>
      </xsl:copy>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

I now need to use additional fields in my source XML and need the existing labels intact but I'm having problems getting this going.

<instance>
  <NewTag>Hello</newTag1>
  <AnotherNewTag>Everyone</AnotherNewTag>
  <InfBy1>Dr Phibes</InfBy1>
  <InfBy2>Dr X</InfBy2>
  <InfBy3>Dr Chivago</InfBy3>
</instance>

It drops the additional labels and outputs

<result xmlns:my="my:my">
  HelloEveryone 
  <items>
    <item>
      <label>Dr Phibes</label>
      <value>60</value>
    </item>
  </items>
  ...

I've been experimenting a lot with

<xsl:otherwise>
  <xsl:copy-of select=".">
  </xsl:copy-of>
</xsl:otherwise>

but being an xsl newbie I can't seem to get this to work. I've a feeling I'm barking up the wrong tree!

Does anyone have any ideas?

Thanks,

Will

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(2

生生不灭 2024-10-30 23:38:08

您的 NewTagAnotherNewTag 元素与 内置模板规则。如果你想要另一种转换,你需要声明这样的规则。

需要保持现有标签完好无损

那么您正在寻找身份规则

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

Your NewTag and AnotherNewTag elements are matched by the Built-in Template Rules. If you want another kind of transformation you need to declare such rules.

need the existing labels intact

Then you are looking for the identity rule

<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>
舂唻埖巳落 2024-10-30 23:38:08

这是 的副作用,它尝试结合隐含的 XSLT“默认行为”为其遇到的每个子节点查找匹配模板。

在您的情况下,它会遇到 ,但这些节点没有模板。

捕获这种情况的默认行为(隐藏的默认模板)将元素的文本值复制到输出流。

的文本值为“Hello”, 的文本值为“Everyone”,因此您会看到“HelloEveryone”。

如果您不想这样做,请编写自己的模板来捕获这些节点:

<xsl:template match="NewTag|AnotherNewTag">
  <xsl:copy-of select="." />
</xsl:template>

或者,编写一个捕获任何未处理的元素节点的模板:

<!-- empty templates do nothing (matched nodes do not appear in the output) -->
<xsl:template match="*" />

如果您想复制未处理的节点不变,但仍想在其中递归应用模板对他们来说,身份模板(@Alejandro 的答案表明了这一点)是可行的方法。

This is a side-effect of <xsl:apply-templates> which tries to find a matching template for every child node it encounters, in conjunction with implied XSLT "default behavior".

In your case, it encounters <NewTag> and <AnotherNewTag>, but there are no templates for these nodes.

The default behavior (the hidden default template) that catches this case copies the text value of the element to the output stream.

The text value of <NewTag> is "Hello", that of <AnotherNewTag> is "Everyone", so you see "HelloEveryone".

If you do not want this, write your own template that catches these nodes:

<xsl:template match="NewTag|AnotherNewTag">
  <xsl:copy-of select="." />
</xsl:template>

Alternatively, write one that catches any unhandled element node:

<!-- empty templates do nothing (matched nodes do not appear in the output) -->
<xsl:template match="*" />

If you want to copy unhandled nodes unchanged but still want to recursively apply templates within them, the identity template (@Alejandro's answer shows it) is the way to go.

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