Я пытаюсь прототипировать преобразование, чтобы превратить xsl:schema
в php-интерфейс. У меня небольшая проблема, xsd:simpleType
элементами xsd:simpleType
которые имеют атрибут name
соответствующий атрибуту type
элементов xsd:element
. Предположим, у меня есть такая схема:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:element name="Foo" type="Bar"/> <xsd:simpleType name="Bar"> <xsd:restriction base="xsd:string"> <xsd:maxLength value="32"/> </xsd:restriction> </xsd:simpleType> </xsd:schema>
Я хотел бы получить следующий результат.
<?php interface Foo { public abstract function buildFooXmlString(Bar $a); }
Вот xslt, который у меня есть до сих пор:
<xsl:stylesheet version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:template match="*"/> <xsl:template match="/"><?php <xsl:apply-templates select="xsd:schema"/></xsl:template> <xsl:template match="xsd:schema">interface FromXsd { <xsl:apply-templates select="xsd:element"/> }</xsl:template> <xsl:template match="xsd:element"> <xsl:apply-templates select="xsd:annotation"/> abstract public function build<xsl:value-of select="normalize-space(@name)"/>XmlString(<xsl:apply-templates select="@type"/>); </xsl:template> <xsl:template match="xsd:annotation">/* <xsl:value-of select="normalize-space()"/> */</xsl:template> <xsl:template match="@type"><xsl:apply-templates select="//xsd:simpleType[@name=normalize-space()]"/></xsl:template> <xsl:template match="xsd:simpleType"><xsl:value-of select="local-name()"/> $a</xsl:template> </xsl:stylesheet>
Он производит большую часть желаемого результата, но не содержит ничего внутри круглых скобок:
<?php interface Foo { public abstract function buildFooXmlString(); }
Как я могу выбрать узел simpleType
с атрибутом name
соответствующим type
element
? (Имена должны быть уникальными для типов xsd.)
Узел simpleType
никогда не выбирается, потому что в шаблоне, где вы сопоставляете xsd:schema
, вы применяете только шаблоны к дочернему поддереву xsd:element
. xsd:simpleType
sibling никогда не будет обработан.
Если вы хотите разрешить обработку всех дочерних узлов узла, вы должны включить пустой <xsl:apply-templates/>
внутри шаблона xsd:schema
.
Это все равно не приведет к желаемому результату. На самом деле это намного проще. Чтобы генерировать фрагмент кода, который вы ожидаете, вам не нужно читать элемент xsd:simpleType
, так как атрибут, который содержит xsd:simpleType
вам тип, может быть непосредственно получен из атрибута @type
элемента xsd:element
с использованием xsd:value-of
, и вы можете просто напечатать $a
сразу после него:
XmlString(<xsl:value-of select="@type"/> $a)
Поскольку вы генерируете текст, вы должны использовать элементы <xsl:text>
для управления распределением пробелов. Например, если вы используете:
<xsl:template match="/"> <xsl:text><?php </xsl:text> <xsl:apply-templates select="xsd:schema"/> </xsl:template>
Вам не нужно беспокоиться о том, чтобы всегда помещать текст <?php
сразу после <xsl:template>
и может обычно отступать от кода. Вы также можете включить новые строки с помощью 

символ (и он не нарушит ваше форматирование):
<xsl:template match="xsd:schema"> <xsl:text>interface FromXsd {
</xsl:text> <xsl:apply-templates select="xsd:element"/><xsl:text>
</xsl:text> <xsl:apply-templates select="xsd:annotation"/> <xsl:text>
}</xsl:text> </xsl:template>
Я отредактировал ваш XSL и внесли эти изменения в документ XSL ниже:
<xsl:stylesheet version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:template match="*"/> <xsl:template match="/"> <xsl:text><?php </xsl:text> <xsl:apply-templates select="xsd:schema"/> </xsl:template> <xsl:template match="xsd:schema"> <xsl:text>interface FromXsd {
</xsl:text> <xsl:apply-templates select="xsd:element"/><xsl:text>
</xsl:text> <xsl:apply-templates select="xsd:annotation"/> <xsl:text>
}</xsl:text> </xsl:template> <xsl:template match="xsd:element"> <xsl:apply-templates select="xsd:annotation"/> <xsl:text> abstract public function build</xsl:text> <xsl:value-of select="normalize-space(@name)"/> <xsl:text>XmlString(</xsl:text> <xsl:value-of select="@type"/><xsl:text> $a</xsl:text> <xsl:text>);</xsl:text> </xsl:template> <xsl:template match="xsd:annotation"> <xsl:text> /* </xsl:text> <xsl:value-of select="normalize-space(.)"/> <xsl:text> */</xsl:text> </xsl:template> </xsl:stylesheet>
Если у вас есть вход, такой как:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:element name="Foo" type="Bar"/> <xsd:simpleType name="Bar"> <xsd:restriction base="xsd:string"> <xsd:maxLength value="32"/> </xsd:restriction> </xsd:simpleType> <xsd:annotation> <xsd:documentation>This is a comment</xsd:documentation> </xsd:annotation> </xsd:schema>
Он даст результат ниже:
<?php interface FromXsd { abstract public function buildFooXmlString(Bar $a); /* This is a comment */ }