XML 2 XML с использованием XSLT - PullRequest
1 голос
/ 20 октября 2010

Я узнал о XSLT и XPath в w3schools, но это не совсем то, что я хотел .. Есть только примеры преобразования XSLT 2 HTML, это довольно просто, но мне нужно преобразование XML 2 XML и я не могу найти хорошее руководство с примерами ... Я скачал MSXSL.exe, но не могу найти примеры использования преобразовать XML ... Кто-нибудь может написать образец? У меня customer.xml:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!--Customers table from Northwind database-->
<Customers>
  <Customer CustomerID="ALFKI">
    <CompanyName>Alfreds Futterkiste</CompanyName>
    <Country>Germany</Country>
    <Orders>
      <Order OrderID="10643">
        <ShipCity>Berlin</ShipCity>
      </Order>
      <Order OrderID="10692">
        <ShipCity>Berlin</ShipCity>
      </Order>
      <Order OrderID="10702">
        <ShipCity>Berlin</ShipCity>
      </Order>
      <Order OrderID="10835">
        <ShipCity>Berlin</ShipCity>
      </Order>
      <Order OrderID="10952">
        <ShipCity>Berlin</ShipCity>
      </Order>
      <Order OrderID="11011">
        <ShipCity>Berlin</ShipCity>
      </Order>
    </Orders>
  </Customer>
  <Customer CustomerID="ANATR">
    <CompanyName>Ana Trujillo Emparedados y helados</CompanyName>
    <Country>Mexico</Country>
    <Orders>
      <Order OrderID="10308">
        <ShipCity>México D.F.</ShipCity>
      </Order>
      <Order OrderID="10625">
        <ShipCity>México D.F.</ShipCity>
      </Order>
      <Order OrderID="10759">
        <ShipCity>México D.F.</ShipCity>
      </Order>
      <Order OrderID="10926">
        <ShipCity>México D.F.</ShipCity>
      </Order>
    </Orders>
  </Customer>
</Customers>

И пытается создать другой XML, который содержит только узлы "страны". Как это написать?

Ответы [ 5 ]

3 голосов
/ 20 октября 2010

Что-то вроде этого должно работать ...

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

  <xsl:template match="/">
    <Countries>
      <xsl:apply-templates select="//Country" mode="copyNode" />
    </Countries>
  </xsl:template>

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

... Вот результат ...

<?xml version="1.0" encoding="utf-8"?>
<Countries>
  <Country>Germany</Country>
  <Country>Mexico</Country>
</Countries>
3 голосов
/ 20 октября 2010

Это точно так же, вам просто нужно использовать атрибут method элемента output соответственно.

1 голос
/ 20 октября 2010

Вот два разных решения : простое и более сложное, которое производит только уникальные страны:

0,1. Получить все Country элементов:

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

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

 <xsl:template match="*[not(self::Country)]">
  <xsl:apply-templates select="*"/>
 </xsl:template>
</xsl:stylesheet>

когда это преобразование применяется к предоставленному XML-документу, получается требуемый, правильный результат :

<Country>Germany</Country>
<Country>Mexico</Country>

0,2. Найти все уникальные страны :

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

    <xsl:key name="kCountryByVal" match="Country" use="."/>

 <xsl:template match="/">
     <xsl:copy-of select=
       "/*/*/Country[generate-id()
                    =
                     generate-id(key('kCountryByVal',.)[1])
                    ]
       "/>
 </xsl:template>
</xsl:stylesheet>

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

С предоставленным XML-документом мы все равно получаем тот же результат:

<Country>Germany</Country>
<Country>Mexico</Country>
1 голос
/ 20 октября 2010

Это довольно просто, вам просто нужно написать xml вместо html внутри ваших шаблонов xslt.

Следующее (непроверенное) должно помочь вам начать:

<xsl:template match="/">
  <Countries>
    <xsl:apply-templates select="Customers/Customer" />
  </Countries>
</xsl:template>

<xsl:template match="Customer">
  <Country>
    <xsl:value-of select="Country" />
  </Country>
</xsl:template>

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

0 голосов
/ 20 октября 2010

В стиле pull это должна быть более короткая таблица стилей, выражающая это преобразование:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="text()"/>
    <xsl:template match="@*|/*|Country|Country/text()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Выход:

<Customers>
    <Country>Germany</Country>
    <Country>Mexico</Country>
</Customers>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...