如何复制xml元素

738*_*560 7 xml xslt xpath xslt-1.0

我必须根据特定的id(例如userid)将xml有效负载复制到尽可能多的xml有效负载中

<ns2:Details xmlns:ns2="ns">
  <ns2:var1>AA0511201143</ns2:var1>
  <ns2:var2>PARCEL</ns2:var2>
  <ns2:var3>04/04/2011</ns2:var3>
  <ns2:var4>Organization</ns2:var4>
  <ns2:UserId>46</ns2:UserId>
  <ns2:UserId>237</ns2:UserId>
</ns2:Details>
Run Code Online (Sandbox Code Playgroud)

我需要输出为

<ns2:Details>
  <ns2:var1>AA0511201143</ns2:var1>
  <ns2:var2>PARCEL</ns2:var2>
  <ns2:var3>04/04/2011</ns2:var3>
  <ns2:var4>Organization</ns2:var4>
  <ns2:UserId>46</ns2:UserId>
</ns2:Details>
<ns2:Details>
  <ns2:var1>AA0511201143</ns2:var1>
  <ns2:var2>PARCEL</ns2:var2>
  <ns2:var3>04/04/2011</ns2:var3>
  <ns2:var4>Organization</ns2:var4>
  <ns2:UserId>237</ns2:UserId>
</ns2:Details>
Run Code Online (Sandbox Code Playgroud)

这可能吗


更新:下面给出的答案工作正常,但我没有提到一个小问题.如果用户标识相同且重复,则应显示相同的xml有效负载.为此,我尝试了以下方法来获取userid的独特元素

<xsl:param name="userId" select="ns0:UserId[generate-id(.)=generate-id(key('k', ns0:UserId)[1])]"/>
Run Code Online (Sandbox Code Playgroud)

但这不起作用,也尝试使用上面

..[generate-id(.)=generate-id(key('k', ns0:UserId)[1])] 
Run Code Online (Sandbox Code Playgroud)

在模板级别它也无法正常工作

我错过了什么吗?

更新:我对上面的代码进行了一些小修改,而不是在xsl:param上工作,我在xsl上使用了它:apply-template

改性前(提供作为答案给我)的<xsl:应用模板选择= "// NS2:详情/ NS2:用户ID"/>变形例的<xsl后:应用模板选择="// NS2:详情/ NS2:用户ID [generate-id(.)= generate-id(key('myUserId',.)[1])]"/>

我的错误是使用ns2:userid而不是"."

完整的xsl代码---

<xsl:output method="xml" indent="yes"/> <xsl:key name="k" match="ns2:UserId" use="text()"/> <xsl:key name="myUserId" match="ns2:UserId" use="."/> <xsl:template match="/"> <ns2:Root> <xsl:apply-templates select="//ns2:Details/ns2:UserId[generate-id(.)=generate-id(key('myUserId', .)[1])]"/> </ns2:Root> </xsl:template>

<xsl:template match="//ns2:Details"> <xsl:param name="userId" select="ns2:UserId"/> <ns2:Details> <xsl:copy-of select="key('k', $userId)[1]"/> <!-- displays UserId values--> <xsl:copy-of select="./*[name() != 'ns2:UserId']"/> <!-- displays other values--> </ns2:Details> </xsl:template>

<xsl:template match="ns2:UserId"> <xsl:apply-templates select=".."> <xsl:with-param name="userId" select="."/> </xsl:apply-templates> </xsl:template>

请验证它.这也对我有用......

Kir*_*huk 4

假设的 XML:

<ns2:Details xmlns:ns2="ns2">
  <ns2:var1>AA0511201143</ns2:var1>
  <ns2:var2>PARCEL</ns2:var2>
  <ns2:var3>04/04/2011</ns2:var3>
  <ns2:var4>Organization</ns2:var4>
  <ns2:UserId>46</ns2:UserId>
  <ns2:UserId>237</ns2:UserId>
  <ns2:UserId>46</ns2:UserId>
</ns2:Details>
Run Code Online (Sandbox Code Playgroud)

XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:ns2="ns2"
>
  <xsl:output method="xml" indent="yes"/>

  <xsl:key name="k" match="ns2:UserId" use="text()"/>

  <xsl:template match="/">
    <root>
      <xsl:apply-templates select="//ns2:Details/ns2:UserId[not(node() = preceding-sibling::node())]"/>
    </root>
  </xsl:template>

  <xsl:template match="//ns2:Details">
    <xsl:param name="userId" select="ns2:UserId"/>

    <ns2:Details>
      <xsl:copy-of select="key('k', $userId)[not(node() = preceding-sibling::node())]"/>
      <xsl:copy-of select="./*[name() != 'ns2:UserId']"/>
    </ns2:Details>
  </xsl:template>

  <xsl:template match="ns2:UserId">
    <xsl:apply-templates select="..">
      <xsl:with-param name="userId" select="."/>
    </xsl:apply-templates>
  </xsl:template>

</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

输出 XML:

<?xml version="1.0" encoding="utf-8"?>
<root xmlns:ns2="ns2">
  <ns2:Details>
    <ns2:UserId>46</ns2:UserId>
    <ns2:var1>AA0511201143</ns2:var1>
    <ns2:var2>PARCEL</ns2:var2>
    <ns2:var3>04/04/2011</ns2:var3>
    <ns2:var4>Organization</ns2:var4>
  </ns2:Details>
  <ns2:Details>
    <ns2:UserId>237</ns2:UserId>
    <ns2:var1>AA0511201143</ns2:var1>
    <ns2:var2>PARCEL</ns2:var2>
    <ns2:var3>04/04/2011</ns2:var3>
    <ns2:var4>Organization</ns2:var4>
  </ns2:Details>
</root>
Run Code Online (Sandbox Code Playgroud)