Удалить элементы иерархии XML с тем же именем, используя XSLT? - PullRequest
1 голос
/ 11 апреля 2019

Ответ XML , который я получаю, содержит одинаковые именованные элементы в ответе, который вызывает у меня проблемы, мне нужно удалить этот повторяющийся элемент, используя XSLT 1.0 . Элемент в ответе <RoundIncidents>. Я просмотрел другие вопросы, но не могу найти то, что мне нужно, чтобы преобразовать ответ в правильный формат.

XML-ответ с повторяющимся элементом

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soap:Body>
      <GetSiteIncidentsResponse xmlns="http://webservices.whitespacews.com/">
         <GetSiteIncidentsResult>
            <ErrorCode>0</ErrorCode>
            <ErrorDescription>Success</ErrorDescription>
            <SuccessFlag>true</SuccessFlag>
            <RoundIncidents>
               <RoundIncidents>
                  <ExtensionData />
                  <AccountSiteID>0</AccountSiteID>
                  <RoundIncidentID>8</RoundIncidentID>
                  <RoundRoundAreaServiceScheduleID>157</RoundRoundAreaServiceScheduleID>
                  <RoundCode>REC1</RoundCode>
                  <ScheduleName>MonFort2</ScheduleName>
                  <ServiceName>Recycling Collection Service</ServiceName>
                  <RoundAreaName>REC1 - MonFort2</RoundAreaName>
                  <RoundIncidentDate>2019-04-08T16:12:10</RoundIncidentDate>
                  <RoundIncidentNotes>Road Closed</RoundIncidentNotes>
                  <RoundIncidentCreatedByID>129</RoundIncidentCreatedByID>
                  <RoundIncidentCreatedDate>2019-04-08T16:12:26.493</RoundIncidentCreatedDate>
               </RoundIncidents>
            </RoundIncidents>
         </GetSiteIncidentsResult>
      </GetSiteIncidentsResponse>
   </soap:Body>
</soap:Envelope>

Желаемый результат после преобразования XSLT

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soap:Body>
      <GetSiteIncidentsResponse xmlns="http://webservices.whitespacews.com/">
         <GetSiteIncidentsResult>
            <ErrorCode>0</ErrorCode>
            <ErrorDescription>Success</ErrorDescription>
            <SuccessFlag>true</SuccessFlag>            
               <RoundIncidents>
                  <ExtensionData />
                  <AccountSiteID>0</AccountSiteID>
                  <RoundIncidentID>8</RoundIncidentID>
                  <RoundRoundAreaServiceScheduleID>157</RoundRoundAreaServiceScheduleID>
                  <RoundCode>REC1</RoundCode>
                  <ScheduleName>MonFort2</ScheduleName>
                  <ServiceName>Recycling Collection Service</ServiceName>
                  <RoundAreaName>REC1 - MonFort2</RoundAreaName>
                  <RoundIncidentDate>2019-04-08T16:12:10</RoundIncidentDate>
                  <RoundIncidentNotes>Road Closed</RoundIncidentNotes>
                  <RoundIncidentCreatedByID>129</RoundIncidentCreatedByID>
                  <RoundIncidentCreatedDate>2019-04-08T16:12:26.493</RoundIncidentCreatedDate>
               </RoundIncidents>            
         </GetSiteIncidentsResult>
      </GetSiteIncidentsResponse>
   </soap:Body>
</soap:Envelope>

1 Ответ

3 голосов
/ 11 апреля 2019

Удаление дочернего элемента

Добавьте шаблон к преобразованию идентичности , который соответствует дочерним элементам, у которых родительский и дочерний элементы имеют одинаковое QName , а дочерний элемент пропущен:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

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

  <xsl:template match="*[name() = name(..)]">
    <xsl:apply-templates select="node()"/>
  </xsl:template>

</xsl:stylesheet>

Демонстрация на удобной XSLT-скрипте Мартина Хоннена.

Обратите внимание, что вышеприведенный лексически сравнивает QNames, которые могут включать префиксы пространства имен.Чтобы правильно сравнить имена ( семантически ), проверьте URI пространства имен:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

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

  <xsl:template match="*[    local-name() = local-name(..) 
                         and namespace-uri() = namespace-uri(..)]">
    <xsl:apply-templates select="node()"/>
  </xsl:template>

</xsl:stylesheet>

Обновлено demo .


Удаление родительского элемента

В обновленном запросе OP, вот как удалить родительский элемент, когда есть дочерний элемент с таким же именем.Выбирая подход, который следует использовать, учтите, что в общем случае у ребенка может быть только один родитель, но у родителя может быть несколько детей.

Простое QName check :

<xsl:template match="*[*[name() = name(..)]]">
  <xsl:apply-templates select="node()"/>
</xsl:template>

URI полного пространства имен check :

<xsl:template match="*[*[    local-name() = local-name(..) 
                         and namespace-uri() = namespace-uri(..)]]">
  <xsl:apply-templates select="node()"/>
</xsl:template>

Credit: Благодаря @ Alejandro и @ michael.hor257k за полезные исправления и улучшения.

...