2013-05-23 12 views
0

Я успешно создал шаблон XSLT для копирования некоторых элементов, смены имен некоторых элементов, из одного файла XML в другой.Переместить элементы в другое место с помощью XSLT

Я не могу понять, как взять элементы и переместить их в другую часть структуры XML.

Я хочу, чтобы преобразовать этот XML:

<Hosts> 
    <Clusters> 
     <Cluster> 
      <Nodes> 
       <WindowsHost/> 
      </Nodes> 
     </Cluster> 
    </Clusters> 
</Hosts> 

к:

<Hosts> 
    <WindowsHosts> 
     <WindowsHost/> 
    </WindowsHosts> 
</Hosts> 

Мой текущий рабочий XSLT содержит:

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

<xsl:template match="/*"> 
    <xsl:copy> 
     <xsl:apply-templates select="*"/> 
    </xsl:copy> 
</xsl:template> 

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

... а затем повторяющиеся шаблоны, как:

<xsl:template match="/Hosts/Clusters/Cluster/Nodes/WindowsHost"> 
    <xsl:copy> 
     <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="/Hosts/Clusters/Cluster/Nodes/WindowsHost/SomeElement"> 
    <xsl:copy> 
     <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 

и так далее. Каждый элемент, который нужно скопировать, имеет свой собственный шаблон, поскольку не все элементы скопированы, а некоторые имена элементов изменены. Но мне удалось изменить имя элемента, а не полный XPath.

Любая помощь будет оценена по достоинству.

Пол


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

В моем существующем XSLT есть шаблон для каждого элемента, который необходимо скопировать из одного XML в другой, поэтому существует множество шаблонов (почти 1000), а начало файла XSLT гарантирует, что с каким-либо элементом по умолчанию ничего не происходит , Короче говоря, я пробовал методы в вашем ответе без успеха, возможно потому, что ситуация не совсем такая, как я показал вам.

Есть три сценария элементов копируются:

  1. Копировать как
  2. Copy, но изменить имя элемента
  3. Копировать в другое место в схеме

Существующее Файл XSLT работает как с # 1, так и с # 2. Это №3, я не могу работать. Вот несколько из XSLT файл

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

<xsl:template match="/*"> 
    <xsl:copy> 
     <xsl:apply-templates select="*"/> 
    </xsl:copy> 
</xsl:template> 

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

<xsl:template match="/SAN/ClientProfile"> 
<!-- copy element as is (working) --> 
    <xsl:copy> 
     <xsl:apply-templates/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="/SAN/ClientProfile/Name"> 
<!-- copy element but change its name (working) --> 
    <CompanyName> 
     <xsl:apply-templates/> 
    </CompanyName> 
</xsl:template> 

<xsl:template match="/SAN/EQLHosts/WindowsClusters/Cluster/ClusterNodes/WindowsHost"> 
<!-- copy to different part of schema (not working) --> 
    <WindowsHost> 
     <xsl:apply-templates/> 
    </WindowsHost> 
</xsl:template> 

Итак, я хочу, чтобы изменить /SAN/EQLHosts/WindowsClusters/Cluster/ClusterNodes/WindowsHost к /SAN/EQLHosts/WindowsHosts/WindowsHost. Все дети этого элемента будут обрабатываться так же, как и те элементы, которые уже скопированы.

Надеюсь, мои разъяснения ясны. Пожалуйста, дайте мне знать, если эта информация изменит ваш ответ или я просто плотный.

Paul

ответ

1

Не похоже, что вы действительно что-то двигаете; просто игнорируя некоторые элементы и добавляя новый элемент WindowsHosts. Попробуйте один сингл indentity transform и измените настройки вашего xsl:apply-templates шаблона /*.

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

Пример:

XML-вход

<Hosts> 
    <Clusters> 
     <Cluster> 
      <Nodes> 
       <WindowsHost/> 
      </Nodes> 
     </Cluster> 
    </Clusters> 
</Hosts> 

XSLT-1,0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

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

    <xsl:template match="/*"> 
     <xsl:copy> 
      <WindowsHosts> 
       <xsl:apply-templates select="@*|Clusters/Cluster/Nodes/WindowsHost"/> 
      </WindowsHosts> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

Выход

<Hosts> 
    <WindowsHosts> 
     <WindowsHost/> 
    </WindowsHosts> 
</Hosts> 

EDIT

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

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

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

    <xsl:template match="/*"> 
     <xsl:copy> 
      <!--Start your select at the first element you need to output and/or modify.--> 
      <xsl:apply-templates select="@*|Clusters/Cluster"/> 
     </xsl:copy> 
    </xsl:template> 

    <!--Example rename--> 
    <xsl:template match="Cluster"> 
     <WindowsHosts> 
      <xsl:apply-templates select="@*|Nodes/WindowsHost"/> 
     </WindowsHosts> 
    </xsl:template> 

</xsl:stylesheet> 

EDIT # 2

Итак, я хочу, чтобы изменить /SAN/EQLHosts/WindowsClusters/Cluster/ClusterNodes/WindowsHost к /SAN/EQLHosts/WindowsHosts/WindowsHost. Все дочерние элементы этого элемента будут обрабатываться так же, как и те, которые уже скопированы .

В этом случае, вы хотите выбрать WindowsHost из EQLHosts ...

<xsl:template match="EQLHosts"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <WindowsHosts> 
      <xsl:apply-templates select="WindowsClusters/Cluster/ClusterNodes/WindowsHost"/> 
     </WindowsHosts> 
    </xsl:copy> 
</xsl:template> 

Если есть другие дети в EQLHosts вам нужно для вывода, вы можете добавить, что к первому xsl:apply-templates. Что-то вроде:

<xsl:apply-templates select="@*|*[not(name()='WindowsClusters')]"/> 
+0

Ваш отзыв очень ценится. Я добавил дополнительную информацию в свой первоначальный пост. –

0

Поскольку комбинируя ответы Даниила с моим существующий файл XSLT не работал, я создал отдельный файл XSLT, чтобы просто переместить эти элементы в новое место в структуре XML.

Этот файл выглядит ...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output indent="yes"/> 
<xsl:strip-space elements="*"/> 

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

<xsl:template match="EQLHosts"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*"/> 
     <WindowsHosts> 
      <xsl:apply-templates select="WindowsClusters/Cluster/ClusterNodes/WindowsHost"/> 
      <xsl:apply-templates select="WindowsClusters/Cluster/VirtualMachines/WindowsHost"/> 
      <xsl:apply-templates select="WindowsHosts/WindowsHost"/> 
     </WindowsHosts> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 

... который прекрасно работает. Этот XSLT-файл включает в себя все элементы, перемещая некоторые.

Мой существующий файл XSLT не содержит всех элементов и только копирует указанные элементы. Поэтому я считаю, что неплохо иметь два файла XSLT, один из них запускается сразу после другого.

Если есть способ их комбинировать, я сохраню их как два.

Смежные вопросы