循环遍历节点并使用 XSLT 将值附加到字符串

Posted

技术标签:

【中文标题】循环遍历节点并使用 XSLT 将值附加到字符串【英文标题】:Loop through nodes and append value to a string using XSLT 【发布时间】:2016-07-18 05:32:00 【问题描述】:

我有以下 XML。在根节点下,我有保存配置的“搜索”节点和有请求的“请求”节点。在“Req”节点内有一个“classId”节点。我正在存储我在这里有一个复杂问题的值。我的最终结果中有一个“appendString”节点。首先,我需要检查“Req”节点内的子节点是否具有值。如果它有值,我需要获取节点名称并匹配 AllClass/class1/node3 中的节点并获取它的值,最后我需要在 'appendString' 节点内形成一个字符串,如下所示 'Childname1=value1,Childname2=值2'。请帮忙。谢谢

我的 XML

<root>
  <ns:Search xmlns:ns="http://example.com/1.0/">
    <ns:AllClass>
      <ns:class1>
        <ns:node1>fhgfjh</ns:node1>
        <ns:node2>Aprtyrtyril</ns:node2>
        <ns:node3>
            <ns:firstChild>Childname1</ns:firstChild>
            <ns:SecondChild>Childname2</ns:SecondChild>
        </ns:node3>
      </ns:class1>
      <ns:class2>
        <ns:node1>dfgd</ns:node1>
        <ns:node2>trytyu</ns:node2>
        <ns:node3>
            <ns:firstChild>Childname11</ns:firstChild>
            <ns:SecondChild>Childname22</ns:SecondChild>
            <ns:ThirdChild>Childname33</ns:ThirdChild>
        </ns:node3>
      </ns:class2>
      .
      .
      .
      .
      .
      .
    </ns:AllClass>
  </ns:Search>
  <ns:Req xmlns:ns="http://example.com/1.0/">
    <ns:classId>class1</ns:classId>
    <ns:className>asdfg</ns:className>
    <ns:firstChild>value1</ns:firstChild>
    <ns:SecondChild>value2</ns:SecondChild>
    <ns:ThirdChild></ns:ThirdChild>
    <ns:FourthChild></ns:FourthChild>
    .
    .
    .
    .
    .
  </ns:Req>
</root>

XSL

<xsl:template match="root/Req">
    <xsl:variable xmlns:ns="http://example.com/1.0/" name="class_tmp" select="/root/ns:Req/ns:classId" />
    <xsl:variable name="class" select="concat(&apos;ns:&apos;,$class_tmp)" />
    <ns1:Response xmlns:ns1="http://example.com/ns/">
      <ns1:SearchString>
        <xsl:value-of xmlns:ns="http://example.com/1.0/" xmlns:ns1="http://example.com/1.0/" select="/root/ns:Search/ns:AllClassM/*[name()=$class]/ns:node2" />
      </ns1:SearchString>
      <xsl:apply-templates/>
    </ns1:Response>
  </xsl:template>
  <xsl:template match="root/Req/*">
    <ns1:appendString></ns1:appendString>
  </xsl:template>

最终的 XML

<ns1:Response xmlns:ns1="http://example.com/ns/">
<ns1:SearchString>Aprtyrtyril</ns1:SearchString>
<ns1:appendString>Childname1=value1,Childname2=value2</ns1:appendString>
</ns1:Response>  

【问题讨论】:

附加您的示例预期结果 XML @nawazlj 添加了示例 XML 【参考方案1】:

--- 根据澄清进行了编辑---

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns="http://example.com/1.0/"
xmlns:ns1="http://example.com/ns/"
exclude-result-prefixes="ns">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:key name="id" match="ns:AllClass/*" use="name()" />
<xsl:key name="label" match="ns:node3/*" use="concat(name(), '|', name(../..))" />

<xsl:template match="/root">
    <xsl:variable name="classId" select="concat('ns:', ns:Req/ns:classId)" />
    <ns1:Response>
        <ns1:SearchString>
            <xsl:value-of select="key('id', $classId)/ns:node2" />
        </ns1:SearchString>
        <ns1:appendString>
            <xsl:for-each select="ns:Req/*[not(self::ns:classId or self::ns:className)][text()]">
                <xsl:value-of select="key('label', concat(name(), '|', $classId))" />
                <xsl:text>=</xsl:text>
                <xsl:value-of select="." />
                <xsl:if test="position()!=last()">
                    <xsl:text>,</xsl:text>
                </xsl:if>
            </xsl:for-each>
        </ns1:appendString>
    </ns1:Response>  
</xsl:template>

</xsl:stylesheet>

这假定除了ns:classIdns:className 之外的ns:Req 下的任何节点都是“子节点”,如果不为空则需要列出。

【讨论】:

谢谢,我会检查 它工作正常,我使用的是第二种方式。但我想要它有点不同。我想获取我在“”这个节点中传递的类的“node3”的值。对于不同的类,firstChild 或 secondChild 中的值可能不同,并且“appendString”应该只包含“node3”中存在的节点,即使“Req”中的所有节点都有值 我不明白你在说什么。我认为您希望appendStringns:classId 中指定的节点的node3 中获取“标签”(Childname1、Childname2)?但我不知道您所说的“firstChild 或 secondChild 中的值对于不同的类可能不同,并且即使 'Req' 中的所有节点都有值,'appendString' 也应该只包含存在于 'node3' 中的节点在里面”。 示例 1.if classId = class1 then appendString => Childname1=value1,Childname2=value2 2. if classId = class2 then appendString => Childname11=value1,Childname22=value2,Childname33=value3 我已经更新XML 我想要在 node3 之前的 classId,所以应该是 而不是 【参考方案2】:

Michael 之前建议的相反方向,下面是工作的 XSLT

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns="http://example.com/1.0/"
xmlns:ns1="http://example.com/ns/"
exclude-result-prefixes="ns">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="id" match="ns:AllClass/*" use="name()" />
<xsl:key name="req" match="ns:Req/*" use="name()" />

<xsl:template match="root">
<xsl:variable name="classId" select="concat('ns:', ns:Req/ns:classId)" />
    <ns1:Response>
        <ns1:SearchString>
            <xsl:value-of select="key('id', $classId)/ns:node2" />
        </ns1:SearchString>
        <ns1:appendString>
            <xsl:for-each select="key('id', $classId)/ns:node3/*">
                <xsl:value-of select="." />
                <xsl:text>=</xsl:text>
                <xsl:value-of select="key('req',name())" />
                <xsl:if test="position()!=last()">
                    <xsl:text>,</xsl:text>
                </xsl:if>
            </xsl:for-each>
        </ns1:appendString>
    </ns1:Response>  
</xsl:template>

</xsl:stylesheet>

【讨论】:

以上是关于循环遍历节点并使用 XSLT 将值附加到字符串的主要内容,如果未能解决你的问题,请参考以下文章

循环遍历 h1 元素并仅输出前 140 个附加省略号的字符

XSLT:分析字符串并保留子节点

将值附加到查询字符串

XSLT:如何将值连接到全局变量

Bash:逐行遍历文件,找到特定的字符串并附加到每个后续行,直到找到相同的字符串

如何将值附加到犰狳矩阵?