当前位置: 首页 > 知识库问答 >
问题:

XSLT从父元素向子节点添加键

颜瀚漠
2023-03-14

我正在将XML导入Access数据库。在转换过程中,数据之间的所有关系都会丢失。使用XSLT,我通过子节点将ID永久化。使用它,其中Id是添加到子节点的父元素:

  <xsl:template match="*[*[not(*)] and ancestor::*[Id]]">
    <xsl:copy>
      <xsl:apply-templates select="ancestor::*[Id]/Id | *"/>
    </xsl:copy>
  </xsl:template>

我使用这种方法遇到的问题是父节点之外还有其他元素也具有Id元素或其变体,例如Account tId或类似的东西。当我尝试在上面的代码之外使用它时,Id的一些实例在以前的节点中丢失了。

   <xsl:template match="*[*[not(*)] and ancestor::*[AccountId]]">
    <xsl:copy>
      <xsl:apply-templates select="ancestor::*[AccountId]/AccountId | *"/>
    </xsl:copy>
  </xsl:template>

很抱歉,我不知道在这里使用合适的语言,因为我对XSLT/XML不太熟悉。。。但我试图实现的是将模板应用程序的焦点缩小到文档节点(基本元素节点?)这样我可以在更精细的层次上应用模板。或者,当存在多个不一定相关的ID实例时,找到一些永久化ID的方法(例如,下面的示例与链接、Alice和平衡节点)。请注意,在第一个输出中,Id一直延续到子节点。

这里有一个例子。

XML:

<Response>


<Alices>
    <Alice>
        <Id>12345</Id>
        <Bobbers>
            <Name>John Doe</Name>
            <Bobs>
                <Bob>
                    <Organization>
                        <Name>John Doe</Name>
                        <ABB>987654</ABB>
                        <ContactDetails>
                            <Adds>
                                <Add>
                                    <Type>Postal</Type>
                                    <Line1>PO BOX 12345</Line1>
                                    <Suburb>Doeville</Suburb>
                                    <State>ENE</State>
                                    <PostCode>1111</PostCode>
                                    <Country>GB</Country>
                                    <Preferred>false</Preferred>
                                </Add>
                                <Add>
                                    <Type>Street</Type>
                                    <Line1>123 Anywhere</Line1>
                                    <Suburb>Doeville</Suburb>
                                    <State>ENE</State>
                                    <PostCode>1111</PostCode>
                                    <Country>GB</Country>
                                    <Preferred>true</Preferred>
                                </Add>
                            </Adds>
                            <PNs>
                                <PN>
                                    <Type>Mobile</Type>
                                    <Number>11111111</Number>
                                    <Preferred>true</Preferred>
                                </PN>
                            </PNs>
                            <EMs>
                                <EM>
                                    <Type>Personal</Type>
                                    <Add>j.doe@anywhere.com</Add>
                                    <Preferred>false</Preferred>
                                </EM>
                            </EMs>
                            <PreferredContactMethod>Email</PreferredContactMethod>
                        </ContactDetails>
                        <Contacts>
                            <Contact>
                                <LastName>Doe</LastName>
                                <FirstName>John</FirstName>
                            </Contact>
                        </Contacts>
                    </Organization>
                </Bob>
            </Bobs>
        </Bobbers>
        <Jons>
            <Jon>
                <Id>012991</Id>
                <PrimaryJon>true</PrimaryJon>
                <StartDate>1900-01-01</StartDate>
            </Jon>
        </Jons>
    </Alice>
        <Movements>
            <Movement>
                <AccountId>J54321</AccountId>
                <InvestmentCode>ABI</InvestmentCode>
                <Exchange>BRU</Exchange>
                <Id>YabbaDabba</Id>
                <Links>
                    <Link>
                        <Id>YabbaDabbaDoo</Id>
                        <Type>Stone</Type>
                    </Link>
                </Links>
            </Movement>
        </Movements>
        <Balances>
            <Balance>
                <AccountId>J54321</AccountId>
                <Value>123456</Value>
                <Investments>
                    <Investment>
                        <Code>JJJ</Code>
                        <UnitBalance>
                            <Total>112.000000</Total>
                        </UnitBalance>
                    </Investment>
                </Investments>
            </Balance>
        </Balances>
</Alices>

</Response>

使用此XSLT,而不使用AcctId模板。注意,我正在将链接节点中的元素名称从Id更改为LinkId,并将其父元素Id更改为TransactionId,以区分两者。

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

  <xsl:output method="xml" indent="yes"/>
  <xsl:strip-space elements="*"/>

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

 
    <xsl:template match="Response/Alices/Movements/Movement/Id">
        <TransactionID>
            <xsl:apply-templates select="@* | node()"/>
        </TransactionID>
    </xsl:template>
    <xsl:template match="@TransactionID">
        <xsl:attribute name="TransactionID">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
    
      <xsl:template match="Response/Alices/Movements/Movement/Links/Link/Id">
        <LinkedTransactionID>
            <xsl:apply-templates select="@* | node()"/>
        </LinkedTransactionID>
    </xsl:template>
    <xsl:template match="@LinkedTransactionID">
        <xsl:attribute name="LinkedTransactionID">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>


  <xsl:template match="*[*[not(*)] and ancestor::*[Id]]">
    <xsl:copy>
      <xsl:apply-templates select="ancestor::*[Id]/Id | *"/>
    </xsl:copy>
  </xsl:template>
 
 
  </xsl:stylesheet>

这就产生了<代码>Id元素从Alice节点一直延续到其子节点。同样在链接节点中,事务ID也从其父节点向下推。XSLT将此事务Id的名称从Id更改为TransactionId。

<Response>
   <Alices>
      <Alice>
         <Id>12345</Id>
         <Bobbers>
            <Id>12345</Id>
            <Name>John Doe</Name>
            <Bobs>
               <Bob>
                  <Organization>
                     <Id>12345</Id>
                     <Name>John Doe</Name>
                     <ABB>987654</ABB>
                     <ContactDetails>
                        <Id>12345</Id>
                        <Adds>
                           <Add>
                              <Id>12345</Id>
                              <Type>Postal</Type>
                              <Line1>PO BOX 12345</Line1>
                              <Suburb>Doeville</Suburb>
                              <State>ENE</State>
                              <PostCode>1111</PostCode>
                              <Country>GB</Country>
                              <Preferred>false</Preferred>
                           </Add>
                           <Add>
                              <Id>12345</Id>
                              <Type>Street</Type>
                              <Line1>123 Anywhere</Line1>
                              <Suburb>Doeville</Suburb>
                              <State>ENE</State>
                              <PostCode>1111</PostCode>
                              <Country>GB</Country>
                              <Preferred>true</Preferred>
                           </Add>
                        </Adds>
                        <PNs>
                           <PN>
                              <Id>12345</Id>
                              <Type>Mobile</Type>
                              <Number>11111111</Number>
                              <Preferred>true</Preferred>
                           </PN>
                        </PNs>
                        <EMs>
                           <EM>
                              <Id>12345</Id>
                              <Type>Personal</Type>
                              <Add>j.doe@anywhere.com</Add>
                              <Preferred>false</Preferred>
                           </EM>
                        </EMs>
                        <PreferredContactMethod>Email</PreferredContactMethod>
                     </ContactDetails>
                     <Contacts>
                        <Contact>
                           <Id>12345</Id>
                           <LastName>Doe</LastName>
                           <FirstName>John</FirstName>
                        </Contact>
                     </Contacts>
                  </Organization>
               </Bob>
            </Bobs>
         </Bobbers>
         <Jons>
            <Jon>
               <Id>12345</Id>
               <Id>012991</Id>
               <PrimaryJon>true</PrimaryJon>
               <StartDate>1900-01-01</StartDate>
            </Jon>
         </Jons>
      </Alice>
      <Movements>
         <Movement>
            <AccountId>J54321</AccountId>
            <InvestmentCode>ABI</InvestmentCode>
            <Exchange>BRU</Exchange>
            <TransactionID>YabbaDabba</TransactionID>
            <Links>
               <Link>
                  <TransactionID>YabbaDabba</TransactionID>
                  <LinkedTransactionID>YabbaDabbaDoo</LinkedTransactionID>
                  <Type>Stone</Type>
               </Link>
            </Links>
         </Movement>
      </Movements>
      <Balances>
         <Balance>
            <AccountId>J54321</AccountId>
            <Value>123456</Value>
            <Investments>
               <Investment>
                  <Code>JJJ</Code>
                  <UnitBalance>
                     <Total>112.000000</Total>
                  </UnitBalance>
               </Investment>
            </Investments>
         </Balance>
      </Balances>
   </Alices>
</Response>

重点放在这一节,这是我特别想看到的:

<Link>
   <TransactionID>YabbaDabba</TransactionID>
   <LinkedTransactionID>YabbaDabbaDoo</LinkedTransactionID>
   <Type>Stone</Type>
</Link>

但是,如果我将其添加到XSLT中,以便将余额节点中的AccountId永久保存到投资节点,则链接节点ID会更改。相关部分低于完整输出。

    <xsl:template match="*[*[not(*)] and ancestor::*[AccountId]]">
    <xsl:copy>
      <xsl:apply-templates select="ancestor::*[AccountId]/AccountId | *"/>
    </xsl:copy>
  </xsl:template>

产生此结果,其中link节点丢失其父节点的ID:

<Response>
   <Alices>
      <Alice>
         <Id>12345</Id>
         <Bobbers>
            <Id>12345</Id>
            <Name>John Doe</Name>
            <Bobs>
               <Bob>
                  <Organization>
                     <Id>12345</Id>
                     <Name>John Doe</Name>
                     <ABB>987654</ABB>
                     <ContactDetails>
                        <Id>12345</Id>
                        <Adds>
                           <Add>
                              <Id>12345</Id>
                              <Type>Postal</Type>
                              <Line1>PO BOX 12345</Line1>
                              <Suburb>Doeville</Suburb>
                              <State>ENE</State>
                              <PostCode>1111</PostCode>
                              <Country>GB</Country>
                              <Preferred>false</Preferred>
                           </Add>
                           <Add>
                              <Id>12345</Id>
                              <Type>Street</Type>
                              <Line1>123 Anywhere</Line1>
                              <Suburb>Doeville</Suburb>
                              <State>ENE</State>
                              <PostCode>1111</PostCode>
                              <Country>GB</Country>
                              <Preferred>true</Preferred>
                           </Add>
                        </Adds>
                        <PNs>
                           <PN>
                              <Id>12345</Id>
                              <Type>Mobile</Type>
                              <Number>11111111</Number>
                              <Preferred>true</Preferred>
                           </PN>
                        </PNs>
                        <EMs>
                           <EM>
                              <Id>12345</Id>
                              <Type>Personal</Type>
                              <Add>j.doe@anywhere.com</Add>
                              <Preferred>false</Preferred>
                           </EM>
                        </EMs>
                        <PreferredContactMethod>Email</PreferredContactMethod>
                     </ContactDetails>
                     <Contacts>
                        <Contact>
                           <Id>12345</Id>
                           <LastName>Doe</LastName>
                           <FirstName>John</FirstName>
                        </Contact>
                     </Contacts>
                  </Organization>
               </Bob>
            </Bobs>
         </Bobbers>
         <Jons>
            <Jon>
               <Id>12345</Id>
               <Id>012991</Id>
               <PrimaryJon>true</PrimaryJon>
               <StartDate>1900-01-01</StartDate>
            </Jon>
         </Jons>
      </Alice>
      <Movements>
         <Movement>
            <AccountId>J54321</AccountId>
            <InvestmentCode>ABI</InvestmentCode>
            <Exchange>BRU</Exchange>
            <TransactionID>YabbaDabba</TransactionID>
            <Links>
               <Link>
                  <AccountId>J54321</AccountId>
                  <LinkedTransactionID>YabbaDabbaDoo</LinkedTransactionID>
                  <Type>Stone</Type>
               </Link>
            </Links>
         </Movement>
      </Movements>
      <Balances>
         <Balance>
            <AccountId>J54321</AccountId>
            <Value>123456</Value>
            <Investments>
               <Investment>
                  <AccountId>J54321</AccountId>
                  <Code>JJJ</Code>
                  <UnitBalance>
                     <AccountId>J54321</AccountId>
                     <Total>112.000000</Total>
                  </UnitBalance>
               </Investment>
            </Investments>
         </Balance>
      </Balances>
   </Alices>
</Response>

重点放在这些节点上:

<Link>
  <AccountId>J54321</AccountId>
  <LinkedTransactionID>YabbaDabbaDoo</LinkedTransactionID>
  <Type>Stone</Type>
</Link>

这个部分现在显示了父母的ID,正如我想要的。

<Investment>
    <AccountId>J54321</AccountId>
    <Code>JJJ</Code>
    <UnitBalance>
      <AccountId>J54321</AccountId>
      <Total>112.000000</Total>
    </UnitBalance>
</Investment>

我认为在这种情况下,问题是节点也有AccountId,一些子节点有Id元素,这两个元素都受到XSLT的影响。因此,如果当有多个ID不一定相关时,我需要将ID从父节点永久保存到子节点,那么我如何编写XSLT,以便我尝试应用到同一节点的模板之间没有冲突?


共有1个答案

商池暝
2023-03-14

可能会限制第二个模板的应用,例如:。

<xsl:template match="*[*[not(*)] and not(Id) and ancestor::*[AccountId]]">

仅在元素没有Id子元素时使用,就像那些Link元素一样。

 类似资料:
  • 我想从父节点复制到子节点。我真的不确定这是如何实现的。 我的源xml 我想得到输出为 我想要XSLT1.0中的解决方案。 我想将这些节点复制到子节点 谢谢。

  • 我有一个XML: 我想向根元素:/doc添加一个属性(名称空间),以便输出如下所示: 我尝试了三种xslt(跳过了默认的“复制所有”部分以减少问题的长度)。 xslt1:见下文,问题在于将空名称空间xmlns=”“添加到/doc的所有子节点(即:/doc/tag1和/doc/tag2) Xslt2:见下文,问题是“ns”被添加到根节点:和 xslt3:请参见下文,问题是报告了错误:未定义名称空间前

  • 我正在使用TestCafe选择器来选择元素。这是一个复杂的Custin Child嵌套场景。 下面是HTML以了解我上面提到的内容: 在图片中,我提到了和,它们是父元素(具有相同的DOM),有一个grand grand child,而另一棵树中相同父元素的grand grand child是。我需要,但需要链接,因为所有父节点都有相同的DOM。

  • 我需要将子元素复制到父元素中。 输入 期望输出 我尝试的内容(输出与输入保持相同): 我肯定会错过一些非常简单的事情。子元素与父元素具有相同的名称,这应该不是问题?

  • 我试图添加一个属性到一个节点,它是CDATA的一部分。我的XML是 结果应该是xml 文档节点中的id属性应作为属性添加到CDATA中的节点。 我能够以字段[@name='CDATA']的形式获取CDATA值,但我不确定如何将文档的属性添加到CDATA中。。 谁能给我建议一下怎么做,或者给我指出正确的方向?

  • 我需要以下xslt代码方面的帮助。我的意见如下: 我的预期输出为: 我曾尝试使用*/text()获取值节点的值,但我只从第一个孩子获得文本。将来我有很多这样的子元素。 提前谢谢。 你好,Minakshi