如何将XML属性更改为元素,然后将它们移动到不同的节点?

如何将XML属性更改为元素,然后将它们移动到不同的节点?,xml,xslt,Xml,Xslt,我想将元素(id,status,type)的属性转换为相关元素的子元素。我已经实现了属性->元素更改,但是如何为结果元素提供正确的父元素呢 以下是一个示例输入文件: <?xml version="1.0" encoding="UTF-8"?> <Customers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" hasMore="false" recordCount="1" responseTime="2017

我想将
元素(
id
status
type
)的属性转换为相关
元素的子元素。我已经实现了属性->元素更改,但是如何为结果元素提供正确的父元素呢

以下是一个示例输入文件:

<?xml version="1.0" encoding="UTF-8"?>
<Customers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" hasMore="false"
    recordCount="1" responseTime="2017-04-27T19:35:02" returnCode="SUCCESS">
<Customer>
<Information>
<FirstName>Brandon</FirstName>
<MiddleName/>
<LastName>Wrong</LastName>
<CustomerStatus>ACTIVE</CustomerStatus>
<Household>false</Household>
<EnrollmentDate xsi:nil="true"/>
<Address>100 Broadway Ave</Address>
<City>San Gabriel</City>
<State>CA</State>
<ZIP>91776-2348</ZIP>
<Country/>
<Phone>6268881212</Phone>
<MobilePhone/>
<Email>BWrong1@gmail.com</Email>
<DateOfBirth xsi:nil="true"/>
</Information>
<Cards>
<Card id="40012345601" status="ACTIVE" type="Customer card"/>
</Cards>
</Customer>
</Customers>

布兰登
错误的
忙碌的
错误的
百老汇大街100号
圣加布里埃尔
加利福尼亚州
91776-2348
6268881212
BWrong1@gmail.com
这是我当前的样式表:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                >

  <xsl:output indent="yes" method="xml" encoding="utf-8" omit-xml-declaration="yes"/>

  <xsl:template match="*">
    <xsl:element name="{local-name()}">
      <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="Customers/@hasMore|Customers/@recordCount|Customers/@returnCode|@xsi:nil|@responseTime" />

    <xsl:template match="Card/@*">
    <xsl:element name="{local-name(.)}">
        <xsl:value-of select="."/> 
    </xsl:element>
  </xsl:template>


  <xsl:template match="@*">
    <xsl:attribute name="{local-name()}">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>

  <xsl:template match="comment() | text() | processing-instruction()">
    <xsl:copy/>
  </xsl:template>

</xsl:stylesheet>

当你把要做的工作放在移动节点上时,你的想法是毫无帮助的。XSL不会改变(或移动)任何东西。相反,它根据输入文档的特征定义结果文档

由于定义输出文档元素的一部分是定义其内容,因此必须在该输出节点的模板上下文中定义输出元素的子节点。因此,对于您的特定情况,您需要一个比您现在使用的身份转换更专门针对
元素定制的模板

但是,在我们继续讨论细节之前,我顺便注意到,您定义的标识转换(扩展为三个单独的模板,并显式使用元素和属性的本地名称)比规范标识转换更详细,没有明显的原因或优势。以下是常见的身份转换,全部在一个模板中:

<xsl:template match="node()|@*">
  <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
</xsl:template>
<xsl:template match="Information">
  <xsl:copy>
    <!-- transform all the element's child nodes -->
    <xsl:apply-templates select="node()"/>
    <!-- include also transformations of the associated <Card> attributes -->
    <xsl:apply-templates select="../Cards/Card/@*" />
  </xsl:copy>
</xsl:template>
您已经拥有的
属性模板可能可以,不过不清楚为什么要使用
local-name()
而不是
name()
。然而,您似乎确实希望避免向输出文档中发出看似无信息的
元素。您可以通过为
提供一个将其转换为零的模板来实现这一点:

<xsl:template match="Cards"/>

综合这些因素,你可能会得出如下结论:

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

  <!-- attributes are not matched or selected for transformation by this
       template: -->
  <xsl:template match="node()">
    <xsl:copy>
      <xsl:apply-templates select="node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- Information elements require a special template: -->
  <xsl:template match="Information">
    <xsl:copy>
      <!-- transform all the element's child nodes -->
      <xsl:apply-templates select="node()|@*"/>
      <!-- include also transformations of the associated <Card> attributes -->
      <xsl:apply-templates select="../Cards/Card/@*" />
    </xsl:copy>
  </xsl:template>

  <!-- transform <Cards> elements to nothing -->
  <xsl:template match="Cards"/>

  <!-- applied only where matching attribute nodes are selected for
       transformation: -->
  <xsl:template match="Card/@*">
    <xsl:element name="{name()}">
      <xsl:value-of select="."/> 
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>


嗨,John,谢谢你修改我的样式表。您非常熟悉XSLT。作为一名新手,我正在学习如何编写xsl作为编程开发的一部分。我真的很感激你的回答,并从你身上学到了一些东西。我想进一步了解XSL学习。你能给我指一下正确的方向吗?作为一名视觉学习者,我正在寻找视频剪辑,以帮助我加快学习过程。如果你知道任何好的培训材料,请与我分享!嗨,约翰,有没有可能去掉这个节点,让它成为现实?我的应用程序将其视为另一个表…@Brandon168,我不推荐非站点资源,这些都是离题的。听起来你正在寻找的资源与我倾向于推荐的不同。谷歌是你的朋友;它将为您提供各种各样的资源。@Brandon168,至于省略
元素,当然,这是可能的。为该元素提供一个只对其子元素应用模板的模板,即不复制节点本身的模板。如果我希望得到如下XML的最终结果,即消除节点但保留节点,我如何更改您提供的xsl以不复制节点本身?
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" method="xml" encoding="utf-8"
              omit-xml-declaration="yes"/>

  <!-- attributes are not matched or selected for transformation by this
       template: -->
  <xsl:template match="node()">
    <xsl:copy>
      <xsl:apply-templates select="node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- Information elements require a special template: -->
  <xsl:template match="Information">
    <xsl:copy>
      <!-- transform all the element's child nodes -->
      <xsl:apply-templates select="node()|@*"/>
      <!-- include also transformations of the associated <Card> attributes -->
      <xsl:apply-templates select="../Cards/Card/@*" />
    </xsl:copy>
  </xsl:template>

  <!-- transform <Cards> elements to nothing -->
  <xsl:template match="Cards"/>

  <!-- applied only where matching attribute nodes are selected for
       transformation: -->
  <xsl:template match="Card/@*">
    <xsl:element name="{name()}">
      <xsl:value-of select="."/> 
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>