使用PHP解析XSD多个模式位置

3

我已经查看了几个关于如何读取XSD的线程,但是我没有得到一个合适的答案。

所以这是我的问题。我有一个包含include元素XSD 文件。因此,它使用多个模式位置。我想在php中读取该文件,以获取创建xml所需的所有必需元素。因此,我的第一步是如何读取XSD文件以获取所有元素,以创建xml文件。

简而言之,我想做什么。

  • 读取XSD以获取创建xml所需的所有必需元素
  • 用我的数据填充xml
  • 保存xml

我想知道的

  • 核心PHP能否做到这一点?
  • 是否有任何现成的脚本可以做到这一点?
  • 我应该创建一个自定义方法来完成这项工作吗?

我尝试过什么

我尝试使用DOMDOCUMENT加载xsd并读取文件,但它不包括多个模式位置文件。

这是我的示例xsd文件

主文件Test.xsd

<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns="http://w3school.com/"
  targetNamespace="http://w3school.com/"
  elementFormDefault="qualified"
  version="2.1">

  <xsd:include schemaLocation="Headers.xsd"/>

  <xsd:element name="head">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="Headers" type="Headers">
          <xsd:annotation>
            <xsd:documentation>
              header
            </xsd:documentation>
          </xsd:annotation>
        </xsd:element>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>

</xsd:schema>

包含文件 Header.xsd

<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns="http://w3school.com/"
  targetNamespace="http://w3school.com/"
  elementFormDefault="qualified"
  version="2.1">


  <xsd:element name="Headers" type="Headers"/>

  <xsd:complexType name="Headers">
    <xsd:sequence>
      <xsd:element name="version" minOccurs="1" default="1.0">
        <xsd:annotation>
          <xsd:documentation>
            This indicates schema version associated with the XML
          </xsd:documentation>
        </xsd:annotation>
        <xsd:simpleType>
          <xsd:restriction base="xsd:string">
            <xsd:enumeration value="1.0" />
            <xsd:enumeration value="0.10.8" />
            <xsd:enumeration value="0.6" />
            <xsd:enumeration value="0.1" />
          </xsd:restriction>
        </xsd:simpleType>
      </xsd:element>
      <xsd:element name="requestId" minOccurs="0">
        <xsd:annotation>
          <xsd:documentation>
            request id
          </xsd:documentation>
        </xsd:annotation>
        <xsd:simpleType>
          <xsd:restriction base="xsd:string">
            <xsd:maxLength value="20"/>
            <xsd:minLength value="1"/>
        </xsd:restriction>
        </xsd:simpleType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>

</xsd:schema>

预期输出

<?xml version="1.0" encoding="UTF-8"?>

<head>
    <Headers>
        <version>1.0</version>
        <requestId></requestId>
    </Headers>
</head>
1个回答

1
我扩展了DOMDocument类,以便递归处理包含文件。看看它是否有所帮助(需要进一步测试!)
class MyDomDoc extends DOMDocument
{
    public function load($filename, $resolveIncludes = true, $options = null)
    {
        chdir(dirname($filename));

        parent::load($filename, $options);

        if ($resolveIncludes) {
            $this->resolveIncludes();
        }
    }

    public function resolveIncludes()
    {
        $this->resolveNodeIncludes($this);
    }

    private function resolveNodeIncludes(DOMNode $node)
    {
        if ($this->isIncludeNode($node)) {
            $included = new static();
            $included->load($node->attributes->getNamedItem('schemaLocation')->textContent);
            $this->replaceIncludedElements($included, $node);
        }
        elseif ($node->childNodes) {
            foreach ($node->childNodes as $node) {
                $this->resolveNodeIncludes($node);
            }
        }
    }

    private function replaceIncludedElements(DOMDocument $included, DOMNode $replace)
    {
        foreach ($included->firstChild->childNodes as $childNode) {
            $replace->parentNode->insertBefore($this->importNode($childNode, true), $replace);
        }

        $replace->parentNode->removeChild($replace);
    }

    private function isIncludeNode(DOMNode $node)
    {
        return $node->localName == 'include' && $node->namespaceURI == 'http://www.w3.org/2001/XMLSchema';
    }
}

使用方法:

$x = new MyDomDoc();
$x->load('path/to/Test.xsd');
echo $x->saveXML();

更新:

好的,从你的评论中可以清楚地看出,你不想“解析”XSD文件(无论是多个模式位置还是其他情况),而是生成符合给定模式的示例XML。我认为你可以使用我回答中的代码从多个位置获取单个XSD,然后在某个工具上使用它来生成示例XML。也许thisthis PHP library(我没有使用过这些工具)。


谢谢你的回应,但这样会返回相同的XSD文件,而我想要它的XML版本。 - Priyank
好的...所以这个过程会稍微有点长。而且我是在运行时生成它,所以可能需要使用库。我猜没有现成的库可以转换它?对吧? - Priyank
@userpk 我进行了一些搜索并找到了我链接的那个。我从未使用过其中任何一个。 - alepeino
这不是我寻找的完美答案,但为了感谢你的努力,我愿意给你悬赏。谢谢。 - Priyank

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接