复杂的 XML XSLT 查询(如 SQL 连接)

发布于 2024-11-25 02:57:51 字数 1990 浏览 7 评论 0原文

我们有一个格式如下所示的 XML 文件。

<toploop id="iamroot">
    <firstinner>
        <inner1 Sequence="001">
          <Number>321</Number>
        </inner1>
        <inner1 Sequence="002">
          <Number>345</Number>
        </inner1>
    </firstinner>
    <secondinner>
        <inner2 Sequence="001">
          <Number>321</Number>
          <secondNumber>189</secondNumber>
        </inner2>
        <inner2 Sequence="002">
          <Number>345</Number>
          <secondNumber>998</secondNumber>
        </inner2>
    </secondinner>
</toploop>

我已经尝试了很多事情,但由于对 XSLT/XPath 不熟悉,我无法获得一个查询来表示如下所示的数据。

iamroot,001,321,189
iamroot,002,345,998

正如您所观察到的,我想检查第一个内部标签的inner1序列,数字是否与第二个内部标签的内部2序列,数字匹配,然后将第二个内部标签的内部2的第二个数字标签值沿着这些标签值拉动。就像 SQL 中的两个表内连接一样。我们可以在 XSLT 中做到这一点吗?我尝试进行值匹配,但不知道如何匹配同一 XML 文件中的数据。请帮忙。提前致谢。我正在使用 Xalan-C 来实现同样的目的。

更新:谢谢 Kay 和 LarsH。我尝试了以下脚本。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output  method="text" />
<xsl:template match="inner2" />   
<xsl:template match="inner1">
<xsl:variable name="inner2" select="../../secondinner/inner2[Number = current()/Number and @Sequence = current()/@Sequence]"/>   
<xsl:if test="$inner2">     
<xsl:value-of select="concat(/toploop/@id, ',', /toploop/firstinner/inner1/@Sequence, ',', /toploop/firstinner/inner1/Number, ',', $inner2/secondNumber, ',')" />
</xsl:if> 
</xsl:template> 
</xsl:stylesheet>

它给出如下所示的输出。

    iamroot,001,321,189,
    iamroot,002,345,998,

如何使这种格式如下所示,没有记录之前的前导空格以及数据行上方和下方不必要的行。

iamroot,001,321,189,

iamroot,002,345,998,

再次感谢。

We have an XML file with the format shown below.

<toploop id="iamroot">
    <firstinner>
        <inner1 Sequence="001">
          <Number>321</Number>
        </inner1>
        <inner1 Sequence="002">
          <Number>345</Number>
        </inner1>
    </firstinner>
    <secondinner>
        <inner2 Sequence="001">
          <Number>321</Number>
          <secondNumber>189</secondNumber>
        </inner2>
        <inner2 Sequence="002">
          <Number>345</Number>
          <secondNumber>998</secondNumber>
        </inner2>
    </secondinner>
</toploop>

I have tried many a things, but being new to XSLT/XPath, I am not able to get a query to represent the data like below.

iamroot,001,321,189
iamroot,002,345,998

As you can observe I want to check if the firstinner tag's inner1 sequence, number matches with the secondinner tag's inner2 sequence, number then pull the secondinner tag's inner2's secondNumber tag value along side of these. Just like a two table Inner join in SQL. Can we do this in XSLT? I was trying with value matching but I dont know how to match the data in the same XML file. Please help. Thanks in advance. I am using Xalan-C for the same.

Update: Thanks Kay and LarsH. I tried the following script.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output  method="text" />
<xsl:template match="inner2" />   
<xsl:template match="inner1">
<xsl:variable name="inner2" select="../../secondinner/inner2[Number = current()/Number and @Sequence = current()/@Sequence]"/>   
<xsl:if test="$inner2">     
<xsl:value-of select="concat(/toploop/@id, ',', /toploop/firstinner/inner1/@Sequence, ',', /toploop/firstinner/inner1/Number, ',', $inner2/secondNumber, ',')" />
</xsl:if> 
</xsl:template> 
</xsl:stylesheet>

Its giving the output like below.

    iamroot,001,321,189,
    iamroot,002,345,998,

How can I make this formatting look like below with out the leading spaces before the records and unnecessary lines above and below the data rows.

iamroot,001,321,189,

iamroot,002,345,998,

Thanks again.

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

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

发布评论

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

评论(2

Spring初心 2024-12-02 02:57:51

像这样的事情:

<xsl:template match="inner1">
  <xsl:variable name="inner2" 
   select="../../secondinner/inner2[Number = current()/Number 
                                    and @Sequence = current()/@Sequence"/>
  <xsl:if test="$inner2">
    <xsl:value-of select="concat(../../@id, ',', @Sequence, ',', 
                          Number, ',', $inner2/secondNumber"/>
  </xsl:if>
</xsl:template>

在这里,您正在两个事物之间进行连接,. 绑定到其中一个,current() 绑定到另一个。

对于允许三个或更多节点集之间连接的更通用的解决方案,您可以绑定显式变量,例如

Something like this:

<xsl:template match="inner1">
  <xsl:variable name="inner2" 
   select="../../secondinner/inner2[Number = current()/Number 
                                    and @Sequence = current()/@Sequence"/>
  <xsl:if test="$inner2">
    <xsl:value-of select="concat(../../@id, ',', @Sequence, ',', 
                          Number, ',', $inner2/secondNumber"/>
  </xsl:if>
</xsl:template>

Here you are doing a join between two things, with . bound to one of them and current() to the other.

For a more general solution that allows joins between three or more node-sets, you can bind explicit variables, for example <xsl:variable name="one" select="."/>.

岁月流歌 2024-12-02 02:57:51

除了修复 @inner2 应该是 $inner2 的拼写错误...

您还需要添加一个模板来“吞掉”您不想处理的元素。现在,默认模板将除inner1 之外的所有元素的字符串内容复制到输出。因此,您需要重写该默认模板,至少对于 inner2 元素而言:

<xsl:template match="inner2" />

该模板为空的事实意味着 元素将被使用,而不输出任何内容,也不处理其后代。

Besides fixing the typo where @inner2 should be $inner2...

You also need to add a template to "swallow" the elements that you don't want to process. Right now, the default template is copying the string content of all elements other than inner1 to the output. So you need to override that default template, at least for inner2 elements:

<xsl:template match="inner2" />

The fact that this template is empty means that <inner2> elements will be consumed without outputting anything, and without processing their descendants.

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