无法获得正确的 XSLT 输出

发布于 2025-01-08 16:36:06 字数 1299 浏览 1 评论 0原文

我有一个像这样的 XML:

<?xml version="1.0" encoding="UTF-8"?>
<Section>
    <Chapter>
        <nametable>
            <namerow>
                <namecell stuff="1">
                    <entity>A</entity>
                </namecell>
                <namecell stuff="2">
                    <entity>B</entity>
                </namecell>
            </namerow>
        </nametable>
    </Chapter>
</Section>

我的 XSLT 是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">

<xsl:output method="text"/>

    <xsl:template match="/">
        <xsl:apply-templates select="Section/Chapter//nametable"/>
    </xsl:template>

    <xsl:template match="nametable">
        <xsl:for-each select="./namerow">
            <xsl:value-of select="./namecell/@stuff"/>
            <xsl:value-of select="./namecell" />
        </xsl:for-each>
    </xsl:template>

<xsl:template match="text()"/>

</xsl:stylesheet>

奇怪的是我得到的输出顺序为 1 2 AB,我以为我会得到 1 A 2 B。

不知道为什么会这样?

蒂亚,

约翰

I have a XML like this:

<?xml version="1.0" encoding="UTF-8"?>
<Section>
    <Chapter>
        <nametable>
            <namerow>
                <namecell stuff="1">
                    <entity>A</entity>
                </namecell>
                <namecell stuff="2">
                    <entity>B</entity>
                </namecell>
            </namerow>
        </nametable>
    </Chapter>
</Section>

My XSLT is like this:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">

<xsl:output method="text"/>

    <xsl:template match="/">
        <xsl:apply-templates select="Section/Chapter//nametable"/>
    </xsl:template>

    <xsl:template match="nametable">
        <xsl:for-each select="./namerow">
            <xsl:value-of select="./namecell/@stuff"/>
            <xsl:value-of select="./namecell" />
        </xsl:for-each>
    </xsl:template>

<xsl:template match="text()"/>

</xsl:stylesheet>

Odd is I'm getting an output in this order 1 2 A B, I thought I'm going to get 1 A 2 B.

Not sure why is that ?.

TIA,

John

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

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

发布评论

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

评论(3

嘿嘿嘿 2025-01-15 16:36:06

您的问题在这里

        <xsl:for-each select="./namerow">
            <xsl:value-of select="./namecell/@stuff"/>
            <xsl:value-of select="./namecell" />
        </xsl:for-each>

与 XSLT 1.0 不同,XSLT 2.0 中的 xsl:value-of 指令输出其 中指定的序列的所有 项代码>选择属性。

这意味着

<xsl:value-of select="./namecell/@stuff"/>

输出所有 stuff 属性(1 和 2),

然后下一条指令:

           <xsl:value-of select="./namecell" />

输出两个 namecell 子项的字符串值 - 分别为 "A"< /code> 和 “B”

解决方案

替换

        <xsl:for-each select="./namerow">
            <xsl:value-of select="./namecell/@stuff"/>
            <xsl:value-of select="./namecell" />
        </xsl:for-each>

        <xsl:for-each select="./namerow">
            <xsl:value-of select="./namecell/(@stuff|entity)"/>
        </xsl:for-each>

经过此修改的完整代码为

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

    <xsl:output method="text"/>

        <xsl:template match="/">
            <xsl:apply-templates select="Section/Chapter//nametable"/>
        </xsl:template>

        <xsl:template match="nametable">
            <xsl:for-each select="./namerow">
                <xsl:value-of select="./namecell/(@stuff|entity)"/>
            </xsl:for-each>
        </xsl:template>

    <xsl:template match="text()"/>
</xsl:stylesheet>

当此转换为应用于提供的 XML 文档

<Section>
    <Chapter>
        <nametable>
            <namerow>
                <namecell stuff="1">
                    <entity>A</entity>
                </namecell>
                <namecell stuff="2">
                    <entity>B</entity>
                </namecell>
            </namerow>
        </nametable>
    </Chapter>
</Section>

产生了想要的结果

1 A 2 B

第二个解决方案(可能是您首先想要做的):

替换

    <xsl:template match="nametable">
        <xsl:for-each select="./namerow">
            <xsl:value-of select="./namecell/@stuff"/>
            <xsl:value-of select="./namecell" />
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="nametable">
        <xsl:for-each select="namerow/namecell">
            <xsl:value-of select="@stuff"/>
            <xsl:value-of select="entity"/>
        </xsl:for-each>
    </xsl:template>

现在你又来了得到想要的结果

1A2B

Your problem is here:

        <xsl:for-each select="./namerow">
            <xsl:value-of select="./namecell/@stuff"/>
            <xsl:value-of select="./namecell" />
        </xsl:for-each>

Unlike in XSLT 1.0 in XSLT 2.0 the xsl:value-of instruction outputs all items of the sequence specified in its select attribute.

This means that

<xsl:value-of select="./namecell/@stuff"/>

outputs all stuff attributes (1 and 2)

then the next instruction:

           <xsl:value-of select="./namecell" />

outputs the string value of the two namecell children -- respectively "A" and "B".

Solution:

Replace:

        <xsl:for-each select="./namerow">
            <xsl:value-of select="./namecell/@stuff"/>
            <xsl:value-of select="./namecell" />
        </xsl:for-each>

with:

        <xsl:for-each select="./namerow">
            <xsl:value-of select="./namecell/(@stuff|entity)"/>
        </xsl:for-each>

The complete code with this modification is:

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

    <xsl:output method="text"/>

        <xsl:template match="/">
            <xsl:apply-templates select="Section/Chapter//nametable"/>
        </xsl:template>

        <xsl:template match="nametable">
            <xsl:for-each select="./namerow">
                <xsl:value-of select="./namecell/(@stuff|entity)"/>
            </xsl:for-each>
        </xsl:template>

    <xsl:template match="text()"/>
</xsl:stylesheet>

and when this transformation is applied on the provided XML document:

<Section>
    <Chapter>
        <nametable>
            <namerow>
                <namecell stuff="1">
                    <entity>A</entity>
                </namecell>
                <namecell stuff="2">
                    <entity>B</entity>
                </namecell>
            </namerow>
        </nametable>
    </Chapter>
</Section>

the wanted result is produced:

1 A 2 B

Second solution (probably what you intended to do in the first place):

Replace:

    <xsl:template match="nametable">
        <xsl:for-each select="./namerow">
            <xsl:value-of select="./namecell/@stuff"/>
            <xsl:value-of select="./namecell" />
        </xsl:for-each>
    </xsl:template>

with:

    <xsl:template match="nametable">
        <xsl:for-each select="namerow/namecell">
            <xsl:value-of select="@stuff"/>
            <xsl:value-of select="entity"/>
        </xsl:for-each>
    </xsl:template>

Now you again get the wanted result:

1A2B
海未深 2025-01-15 16:36:06

我正在使用 msxml,得到 1 A 作为操作:|

那么这里有一个适合您的解决方案,它的工作原理就像 gem :)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">

  <xsl:output method="text"/>

  <xsl:template match="/Section/Chapter/nametable/namerow/namecell">
    <xsl:value-of select="@stuff"/>
    <xsl:text> </xsl:text><!--inserting a space-->
    <xsl:value-of select="entity"/>
    <xsl:text> </xsl:text><!--inserting a space-->
  </xsl:template>
  <xsl:template match="text()"/>

</xsl:stylesheet>

I am using msxml, am getting 1 A as op :|

Well here is a solution for you it works like gem :)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">

  <xsl:output method="text"/>

  <xsl:template match="/Section/Chapter/nametable/namerow/namecell">
    <xsl:value-of select="@stuff"/>
    <xsl:text> </xsl:text><!--inserting a space-->
    <xsl:value-of select="entity"/>
    <xsl:text> </xsl:text><!--inserting a space-->
  </xsl:template>
  <xsl:template match="text()"/>

</xsl:stylesheet>
猫腻 2025-01-15 16:36:06

您看到的行为的原因是您迭代了 namerow。如果您将 namecell 迭代为:<,您将得到 1A2B xsl:选择的值=“。” />。您需要记住,每个 XPath(例如 @stuff)不一定提供一个值(节点),而是提供一组值(节点集)。该集合通常碰巧只包含一个值,但不要被愚弄。

同一件事的另一种语法:

PS 就像在文件系统路径中一样,您不必在 XPath 之前写入“./”。

The reason for the behavior you see is that you iterate over namerow. You will get 1A2B if you will instead iterate over namecell as: <xsl:for-each select="namerow/namecell"><xsl:value-of select="@stuff"/><xsl:value-of select="." /></xsl:for-each>. You'll want to remember that each XPath such as @stuff gives you not necessarily one value (a node), but rather a set of values (a nodeset). That set will commonly happen to contain only one value, but don't be fooled.

Another syntax for the same thing: <xsl:for-each select="namerow"><xsl:for-each select="namecell"><xsl:value-of select="@stuff"/><xsl:value-of select="." /></xsl:for-each></xsl:for-each>

P.S. Just as in a filesystem path, you don't have to write "./" before an XPath.

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