XSLT — объединение нескольких атрибутов (объединение) после выравнивания xml

#xml #xslt

#xml #xslt

Вопрос:

У меня есть простой xml, который я выравниваю (элементы к атрибутам)

ввод xml

 <?xml version="1.0" ?>
<queryResponse type="Clients" rootUrl="https://10.130.0.192/webacs/api/v1/data" requestUrl="https://10.30.0.192/webacs/api/v1/data/Clients?.full=trueamp;amp;.firstResult=0amp;amp;.maxResults=1000" responseType="listEntityInstances" count="349" first="0" last="348">
  <entity url="https://10.130.0.192/webacs/api/v1/data/Clients/621621" type="Clients" dtoType="clientsDTO">
    <clientsDTO id="621621" displayName="621621">
      <associationTime>1474746255456</associationTime>
      <clientInterface>GigabitEthernet1/0/16</clientInterface>
      <connectionType>WIRED</connectionType>
      <deviceIpAddress>10.1.1.254</deviceIpAddress>
      <deviceName>stack</deviceName>
      <deviceType>Unknown</deviceType>
      <ipAddress>10.30.0.106</ipAddress>
      <location>Unknown</location>
      <macAddress>macaddress</macAddress>
      <protocol>DOT3</protocol>
      <securityPolicyStatus>PASSED</securityPolicyStatus>
      <status>ASSOCIATED</status>
      <updateTime>1474746256758</updateTime>
      <vendor>Netapp</vendor>
      <vlan>vlan_300_server</vlan>
      <vlanId>300</vlanId>
    </clientsDTO>
  </entity>
 </queryResponse>
  

xslt:

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

  <xsl:template match="queryResponse">
    <Data>
      <xsl:apply-templates/>
    </Data>
  </xsl:template>

  <xsl:template match="clientsDTO">
    <Client>
      <xsl:for-each select="descendant::*[not(*)]">
        <xsl:attribute name="{name()}">
          <xsl:value-of select="text()"/>
        </xsl:attribute>

      </xsl:for-each>
    </Client>
  </xsl:template>
</xsl:stylesheet>
  

который отлично работает и предоставляет мне мой сглаженный выходной xml.

Теперь с этим XSLT я хотел бы добавить еще одну вещь. Элементы clientInterface и DeviceName должны быть (дополнительно) объединены в качестве нового атрибута.

Есть идеи о том, как этого добиться?

Обновить:

Мой текущий выходной xml выглядит следующим образом:

 <?xml version="1.0" encoding="UTF-8"?>
<Data>
   <Client associationTime="1474746255456" clientInterface="GigabitEthernet1/0/16" connectionType="WIRED" deviceIpAddress="10.1.1.254" deviceName="stack" deviceType="Unknown" ipAddress="10.130.0.106" location="Unknown" macAddress="macaddress" protocol="DOT3" securityPolicyStatus="PASSED" status="ASSOCIATED" updateTime="1474746256758" vendor="Netapp" vlan="vlan_300_server" vlanId="300" />
</Data>
  

Теперь внутри этого » я хотел бы иметь новый атрибут, который объединяет DeviceName и clientInterface, что приводит к:

 <?xml version="1.0" encoding="UTF-8"?>
<Data>
   <Client **deviceId="stack_GigabitEthernet1/0/16"**associationTime="1474746255456" clientInterface="GigabitEthernet1/0/16" connectionType="WIRED" deviceIpAddress="10.1.1.254" deviceName="stack" deviceType="Unknown" ipAddress="10.130.0.106" location="Unknown" macAddress="macaddress" protocol="DOT3" securityPolicyStatus="PASSED" status="ASSOCIATED" updateTime="1474746256758" vendor="Netapp" vlan="vlan_300_server" vlanId="300" />
</Data>
  

Комментарии:

1. Возможно, вы также можете добавить желаемый выходной xml в свой вопрос для большей ясности.

2. Добавлено то, что я получил до сих пор, и чего я хотел бы достичь. новый элемент находится в ** и называется DeviceID

Ответ №1:

Вы могли бы сделать:

 <xsl:template match="clientsDTO">
    <Client>
        <xsl:attribute name="deviceId">
            <xsl:value-of select="deviceName"/>
            <xsl:text>_</xsl:text>
            <xsl:value-of select="clientInterface"/>
        </xsl:attribute>
        <xsl:for-each select="*[not(*)]">
            <xsl:attribute name="{name()}">
                <xsl:value-of select="."/>
            </xsl:attribute>
        </xsl:for-each>
    </Client>
</xsl:template>
  

Примечание: использование descendant оси неэффективно — и в вашем случае не нужно.

Комментарии:

1. Идеально! Кажется, делает именно то, что я хочу. Потомок действительно все еще оставался остатком от предыдущего преобразования (где это имело смысл), но его можно удалить здесь.