我正在尝试构建一个转换原型(prototype),将 xsl:schema
转换为 PHP 界面。我在匹配 xsd:simpleType
元素时遇到了一些麻烦,这些元素的 name
属性与 xsd:element< 的
元素。假设我有这样的架构:type
属性相匹配
<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();
}
如何选择 name
属性与 element
的 type
匹配的 simpleType
节点? (xsd 类型的名称必须是唯一的。)
最佳答案
simpleType
节点永远不会被选择,因为在模板中您匹配 xsd:schema
,您只需将模板应用到 xsd:element
子子树。 xsd:simpleType
sibling 永远不会被处理。
如果您想允许处理节点的所有子节点,则应包含一个空 <xsl:apply-templates/>
里面xsd:schema
模板。
这仍然不会产生你想要的结果。实际上要简单得多。要生成您期望的代码片段,您不需要阅读 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 */
}
关于php - 将元素与动态属性值相匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23189178/