【问题标题】:Create XML based on 2 XMLs and looking up values in both files using XSLT2.0基于 2 个 XML 创建 XML,并使用 XSLT2.0 在两个文件中查找值
【发布时间】:2020-04-29 12:06:02
【问题描述】:

我正在尝试生成基于其他 2 个 XML 的 XML。我正在轮询一个返回人员详细信息的数据库(查询中可以返回 n 个人)。 最终的 XML 应该具有与来自 DB 的 XML 中的 不同名称标签一样的确切数量的 数据标签。例如:

第一个 XML - 从 DB 获取它

<parent>
    <child>
        <name>John</name>
        <city>Boston</city>
    </child>
    <child>
        <name>John</name>
        <city>Seattle</city>
    </child>
    <child>
        <name>Allison</name>
        <city>Houston</city>
    </child>
</parent>

第二个 XML - 从另一个来源获取这个

<details>
    <parent>
        <detail>
            <city>Boston</city>
            <code>abc</code>
        </detail>
        <detail>
            <city>Houston</city>
            <code>xyz</code>
        </detail>
    </parent>
    <parent>
        <detail>
            <city>Boston</city>
            <code>abc</code>
        </detail>
        <detail>
            <city>Seattle</city>
            <code>mno</code>
        </detail>
    </parent>
    <parent>
        <detail>
            <city>Houston</city>
            <code>xyz</code>
        </detail>
        <detail>
            <city>Seattle</city>
            <code>mno</code>
        </detail>
    </parent>
</details>

首先我需要创建 2 个数据标签,因为有 2 个不同的名称 - John 和 Allison(这部​​分已经完成并且运行良好)。 然后我需要检查 John,无论返回的 DB 行中是否存在唯一的城市标签。让我们考虑第一个 XML,我们有与波士顿和西雅图有关的 John。因此,我将一一检查第二个 XML 中的这些城市,对于我匹配的每个 parent 标签,我将创建一个新标签 details 并粘贴所有相关内容.

1) 如果没有匹配的条目,则不应创建详细信息标签,因为没有匹配的条目。

2) city 标签将位于 parent 标签之下。 city 标签的值在 parent 标签内是唯一的。我必须在第二个 XML 中一一匹配 city 并从所有匹配的 city 标记中获取值,从第二个 XML 的所有父项中获取值,并以任何方式填充在 parent 标记中匹配的内容会出现在输出 XML 中的相应 detail 标记中。 PFB 示例 XML,可以更好地解释 -

最终预期的 XML-

<FinalData>
    <Data>
        <name>John</name>
        <details>
            <detail>
                <city value="Boston">abc</city>
            </detail>
            <detail>
                <city value="Boston">abc</city>
                <city value="Seattle">mno</city>
            </detail>
            <detail>
                <city value="Seattle">mno</city>
            </detail>
        </details>
    </Data>
    <Data>
        <name>Allison</name>
        <details>
            <detail>
                <city value="Houston">xyz</city>
            </detail>
            <detail>
                <city value="Houston">xyz</city>
            </detail>
        </details>
    </Data>
</FinalData>

目前我的 XSLT 导致如下所示 -

<FinalData>
    <Data>
        <name>John</name>
        <details>
            <detail>
                <city value="Boston">abc</city>
                <city value="Boston">abc</city>
                <city value="Seattle">mno</city>
                <city value="Seattle">mno</city>
            </detail>
        </details>
    </Data>
    <Data>
        <name>Allison</name>
        <details>
            <detail>
                <city value="Houston">xyz</city>
                <city value="Houston">xyz</city>
            </detail>
        </details>
    </Data>
</FinalData>

希望这很清楚,因为我不擅长解释。

【问题讨论】:

    标签: xml xslt xslt-2.0 xslt-grouping xslkey


    【解决方案1】:

    使用键来解决交叉引用:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        exclude-result-prefixes="#all"
        version="3.0">
    
      <xsl:param name="details">
    <details>
        <parent>
            <detail>
                <city>Boston</city>
                <code>abc</code>
            </detail>
            <detail>
                <city>Houston</city>
                <code>xyz</code>
            </detail>
        </parent>
        <parent>
            <detail>
                <city>Boston</city>
                <code>abc</code>
            </detail>
            <detail>
                <city>Seattle</city>
                <code>mno</code>
            </detail>
        </parent>
        <parent>
            <detail>
                <city>Houston</city>
                <code>xyz</code>
            </detail>
            <detail>
                <city>Seattle</city>
                <code>mno</code>
            </detail>
        </parent>
    </details>      
      </xsl:param>
    
      <xsl:key name="parent-ref" match="parent" use="detail/city"/>
      <xsl:key name="detail-ref" match="parent/detail" use="city"/>
    
      <xsl:output method="xml" indent="yes" />
    
      <xsl:template match="parent">
        <FinalData>
            <xsl:for-each-group select="child" group-by="name">
                <Data>
                    <xsl:copy-of select="name"/>
                </Data>
                <Details>
                    <xsl:apply-templates select="key('parent-ref', current-group()/city, $details)"/>
                </Details>
            </xsl:for-each-group>
        </FinalData>
      </xsl:template>
    
      <xsl:template match="details/parent">
          <detail>
              <xsl:apply-templates select="key('detail-ref', current-group()/city, .)"/>
          </detail>
      </xsl:template>
    
      <xsl:template match="detail">
          <city value="{city}">
              <xsl:value-of select="code"/>
          </city>
      </xsl:template>
    
    </xsl:stylesheet>
    

    https://xsltfiddle.liberty-development.net/gVhDDyY

    为了完整起见,第二个文档是内联的,但您当然可以改用&lt;xsl:param name="details" select="doc('details.xml')"/&gt;

    【讨论】:

    • 完美。这对我有用,但我在理解逻辑方面有点困难,因为我不擅长 keys 而这里我们使用 2 个键。如果您能简要解释一下这是如何工作的,那就太好了?
    • @Kartik,您是否尝试过阅读 XSLT 教程或书籍(如 cranesoftwrights.github.io/books/ptux/index.htm,仅列出在线可用的一个)中的部分键来理解键?也许从那里开始,如果您没有设法将那里的介绍应用到这个案例中,那么请提出一个新的具体问题。键的声明指示 XSLT 处理器通过 use 表达式“索引”matched 节点,然后 key 函数允许使用键值有效地选择/搜索节点。
    • 有什么方法可以在 apply-template 部分匹配时从第一个 XML 中提取 city 而不是从第二个 XML 中获取值它在哪里匹配模板?如果您看到下面的代码 sn-p, &lt;xsl:template match="detail"&gt; &lt;city value="{city}"&gt; // 这里我想要来自第一个 XML 而不是第二个 XML 的 city 标记值。
    • @karD,请提出新问题,即使是相关问题,作为一个新的、单独的问题,并提供必要的详细信息。
    • 谢谢,已将其发布在这里 stackoverflow.com/questions/62195646/… 。如果您能帮助我,将不胜感激。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-24
    相关资源
    最近更新 更多