Переименовывать узлы с XSLT

Я пробую что-то очень простое, но по какой-то причине это не работает. В принципе, мне нужно переименовать некоторые узлы в XML-документе. Таким образом, я создал файл XSLT для выполнения преобразования.

вот пример XML:

EDIT: адреса и элементы адреса встречаются на многих уровнях. Это то, что заставило меня попытаться применить XSLT. Функция набора типизированных данных Visual Studio, которая создает типизированные наборы данных из XSD-файлов, не позволяет вложенные ссылки на ту же таблицу. Таким образом, наличие предприятий/бизнес/адреса и предприятия/Бизнес/Контакт/адреса приводит к сбою Load (). Это известная проблема, и все они вам скажут что-то вроде "нет вложенных таблиц...отредактируйте свой XSD, чтобы прекратить это."К сожалению, это означает, что мы должны применить XSLT, чтобы XML соответствовал "взломанному" XSD, так как файлы поступают от стороннего поставщика.

Итак, мы очень близки с помощью здесь оказываться. Последние две вещи таковы:--5-->

1.) Как я могу использовать ссылку на пространство имен в атрибуте match шаблона xsl:, чтобы указать, что я хочу переименовать предприятия/бизнес/адреса в BusinessAddresses, но переименовать предприятия/бизнес/контакты/контакт/адреса в ContactAddresses?

2.) Как я могу остановить XSLT от загромождения каждого нового элемента явными ссылками на пространство имен? Оно причиняет весьма коптит в выход.

Я создал пространство имен под названием "сталь", и имел хороший успех с:

<xsl:template match="steel:Addresses>
  <xsl:element name="BusinessAddresses>
</xsl:template>

очевидная проблема здесь в том, что он переименовывает все из элементов адресов в BusinessAddresses, хотя я хочу, чтобы некоторые из них назывались ContactAddresses и так далее. Ненужное добавление явных ссылок на пространство имен ко всем переименованным узлам также вызывает проблемы.

Я пробовал такие вещи, но как только я добавляю косые черты к матчу атрибут, это синтаксическая ошибка в XSLT, например:

<xsl:template match="steel:/Businesses/Business/Addresses">

Я чувствую себя очень близко, но мне нужно некоторое руководство о том, как смешивать использование пространства имен и способ использовать косые черты для выбора любой узлы под определенными путями.

<?xml version="1.0"?>
<Businesses>
  <Business>
    <BusinessName>Steel Stretching</BusinessName>
    <Addresses>
      <Address>
        <City>Pittsburgh</City>
      </Address>
      <Address>
        <City>Philadelphia</City>
      </Address>
    </Addresses>
    <Contacts>
      <Contact>
        <FirstName>Paul</FirstName>
        <LastName>Jones</LastName>
        <Addresses>
          <Address>
            <City>Pittsburgh</City>
          </Address>
        </Addresses>
      </Contact>
    </Contacts>
  </Business>
  <Business>
    <BusinessName>Iron Works</BusinessName>
    <Addresses>
      <Address>
        <City>Harrisburg</City>
      </Address>
      <Address>
        <City>Lancaster</City>
      </Address>
    </Addresses>
  </Business>
</Businesses>

мне нужно переименовать адреса в BusinessAddresses, и мне нужно переименовать адрес в BusinessAddress для каждого экземпляра адресов и адресов непосредственно под бизнес-узлом. Мне также нужно переименовать адреса в ContactAddresses, и мне нужно переименовать адрес в ContactAddress для каждого экземпляра адресов и адреса непосредственно под контактным узлом.

Я пробовал несколько решений, но ни одно из них не работает. Все они в конечном итоге производят тот же XML, что и исходный файл.

вот пример того, что я пробовал:

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

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

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

Это было попробовано по крайней мере в 6 различных вкусах, в комплекте с шагом через отладчик XSLT в VB.Net - ... Он никогда не выполняет шаблон соответствует адресам.

Почему?

2 ответов


почему XSLT может потерпеть неудачу?

XSLT потерпит неудачу из-за очевидных вещей, таких как опечатки. Однако наиболее вероятная ситуация связана с использованием пространства имен. Если вы объявили пространство имен по умолчанию для XML, но не включили его в XSLT, XSLT не будет соответствовать шаблонам, как можно было бы ожидать.

в следующем примере добавляется xmlns:business атрибут, который объявляет, что элементы, квалифицированные business префикс принадлежит пространству имен mynamespace.uri. Затем я использовал этот префикс для определения соответствия адресов и шаблонов адресов. Конечно, вам нужно будет изменить URI пространства имен на то, что соответствует пространству имен по умолчанию вашего XML-файла.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                xmlns:business="mynamespace.uri"
                exclude-result-prefixes="msxsl">
  <xsl:template match="/">
    <xsl:apply-templates select="@*|node()"/>
  </xsl:template>

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

  <xsl:template match="business:Addresses">
    <xsl:element name="BusinessAddresses">
      <xsl:apply-templates select="@*|node()" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="business:Address">
    <xsl:element name="BusinessAddress">
      <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

как вы сопоставляете шаблоны на основе местоположения элемента, а также имени?

есть несколько способов достичь этой последней части вашей проблемы, BusinessAddress или ContactAddress, но самый простой-изменить шаблон match атрибуты для рассмотрения родительских узлов. Если вы думаете о match атрибут как путь в XML для узла, эта опция становится более ясной (содержимое шаблонов, оставленных для краткости):

<xsl:template match="business:Business/business:Addresses>
</xsl:template>

<xsl:template match="business:Business/business:Addresses/business:Address">
</xsl:template>

<xsl:template match="business:Contact/business:Addresses">
</xsl:template>

<xsl:template match="business:Contact/business:Addresses/business:Address">
</xsl:template>

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


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

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

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

<xsl:template match="*">
 <xsl:copy-of select="."/>
</xsl:template>

<xsl:template match="Addresses">
 <BusinessAddresses>
  <xsl:apply-templates/>
 </BusinessAddresses>
</xsl:template>

<xsl:template match="Addresses/Address">
 <BusinessAddress>
  <xsl:value-of select="."/>
 </BusinessAddress>
</xsl:template>

</xsl:stylesheet>